Java에서 시간 초과로 차단 메서드를 호출하는 표준 좋은 방법이 있습니까? 나는 할 수 있기를 원한다 :
// call something.blockingMethod();
// if it hasn't come back within 2 seconds, forget it
그게 말이된다면.
감사.
답변
Executor를 사용할 수 있습니다.
ExecutorService executor = Executors.newCachedThreadPool();
Callable<Object> task = new Callable<Object>() {
public Object call() {
return something.blockingMethod();
}
};
Future<Object> future = executor.submit(task);
try {
Object result = future.get(5, TimeUnit.SECONDS);
} catch (TimeoutException ex) {
// handle the timeout
} catch (InterruptedException e) {
// handle the interrupts
} catch (ExecutionException e) {
// handle other exceptions
} finally {
future.cancel(true); // may or may not desire this
}
(가) 경우 future.get
오초에 반환하지 않습니다, 그것은을 던졌습니다 TimeoutException
. 시간 제한은 초, 분, 밀리 초 또는 상수로 사용 가능한 모든 단위로 구성 할 수 있습니다.TimeUnit
.
자세한 내용은 JavaDoc 을 참조하십시오 .
답변
호출을 a로 래핑하고 FutureTask
get ()의 제한 시간 버전을 사용할 수 있습니다.
http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/FutureTask.html을 참조하십시오.
답변
뒤에서 Executor를 사용하는 Guava의 TimeLimiter 를 참조하십시오 .
답변
jcabi-aspects 라이브러리 를 사용하는 AspectJ 솔루션도 있습니다.
@Timeable(limit = 30, unit = TimeUnit.MINUTES)
public Soup cookSoup() {
// Cook soup, but for no more than 30 minutes (throw and exception if it takes any longer
}
더 간결해질 수는 없지만 AspectJ에 의존하고 빌드 라이프 사이클에 도입해야합니다.
더 자세히 설명하는 기사가 있습니다. Java 메소드 실행 시간 제한
답변
사람들이 이것을 여러 방법으로 구현하려고 시도하는 것은 정말 대단합니다. 그러나 진실은 방법이 없다는 것입니다.
대부분의 개발자는 차단 호출을 다른 스레드에 넣고 미래 또는 일부 타이머를 사용하려고합니다. 그러나 Java에서는 스레드 중단을 명시 적으로 처리하는 Thread.sleep () 및 Lock.lockInterruptibly () 메서드와 같은 몇 가지 매우 특정한 경우는 말할 것도없고 외부 적으로 스레드를 중지 할 수있는 방법이 없습니다.
따라서 실제로는 세 가지 일반 옵션 만 있습니다.
-
차단 호출을 새 스레드에 놓고 시간이 만료되면 계속 진행하여 해당 스레드를 중단합니다. 이 경우 스레드가 데몬 스레드로 설정되어 있는지 확인해야합니다. 이렇게하면 스레드가 애플리케이션 종료를 중지하지 않습니다.
-
비 차단 Java API를 사용하십시오. 예를 들어 네트워크의 경우 NIO2를 사용하고 비 차단 방법을 사용하십시오. 콘솔에서 읽으려면 차단하기 전에 Scanner.hasNext () 등을 사용하십시오.
-
차단 호출이 IO가 아니라 논리 인 경우 반복적으로
Thread.isInterrupted()
외부에서 중단되었는지 확인thread.interrupt()
하고 차단 스레드에서 다른 스레드 호출 을 수행 할 수 있습니다.
동시성에 대한이 과정 https://www.udemy.com/java-multithreading-concurrency-performance-optimization/?couponCode=CONCURRENCY
Java에서 작동하는 방식을 정말로 이해하고 싶다면 이러한 기본 사항을 설명합니다. 실제로 이러한 특정 제한 및 시나리오에 대해 설명하고 강의 중 하나에서 이에 대해 설명합니다.
저는 개인적으로 가능한 한 차단 호출을 사용하지 않고 프로그래밍하려고합니다. 예를 들어 Vert.x와 같은 툴킷은 IO를 수행하고 IO 작업을 비동기식으로 비 차단 방식으로 수행하는 것을 정말 쉽고 성능있게 만들어줍니다.
도움이 되길 바랍니다
답변
Thread thread = new Thread(new Runnable() {
public void run() {
something.blockingMethod();
}
});
thread.start();
thread.join(2000);
if (thread.isAlive()) {
thread.stop();
}
stop은 더 이상 사용되지 않으며 더 나은 대안은 휘발성 부울 플래그를 설정하는 것입니다 .blockingMethod () 내부에서 다음과 같이 확인하고 종료하십시오.
import org.junit.*;
import java.util.*;
import junit.framework.TestCase;
public class ThreadTest extends TestCase {
static class Something implements Runnable {
private volatile boolean stopRequested;
private final int steps;
private final long waitPerStep;
public Something(int steps, long waitPerStep) {
this.steps = steps;
this.waitPerStep = waitPerStep;
}
@Override
public void run() {
blockingMethod();
}
public void blockingMethod() {
try {
for (int i = 0; i < steps && !stopRequested; i++) {
doALittleBit();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
public void doALittleBit() throws InterruptedException {
Thread.sleep(waitPerStep);
}
public void setStopRequested(boolean stopRequested) {
this.stopRequested = stopRequested;
}
}
@Test
public void test() throws InterruptedException {
final Something somethingRunnable = new Something(5, 1000);
Thread thread = new Thread(somethingRunnable);
thread.start();
thread.join(2000);
if (thread.isAlive()) {
somethingRunnable.setStopRequested(true);
thread.join(2000);
assertFalse(thread.isAlive());
} else {
fail("Exptected to be alive (5 * 1000 > 2000)");
}
}
}
답변
이 시도. 더 간단한 솔루션. 시간 제한 내에 if 블록이 실행되지 않았 음을 보장합니다. 프로세스가 종료되고 예외가 발생합니다.
public class TimeoutBlock {
private final long timeoutMilliSeconds;
private long timeoutInteval=100;
public TimeoutBlock(long timeoutMilliSeconds){
this.timeoutMilliSeconds=timeoutMilliSeconds;
}
public void addBlock(Runnable runnable) throws Throwable{
long collectIntervals=0;
Thread timeoutWorker=new Thread(runnable);
timeoutWorker.start();
do{
if(collectIntervals>=this.timeoutMilliSeconds){
timeoutWorker.stop();
throw new Exception("<<<<<<<<<<****>>>>>>>>>>> Timeout Block Execution Time Exceeded In "+timeoutMilliSeconds+" Milli Seconds. Thread Block Terminated.");
}
collectIntervals+=timeoutInteval;
Thread.sleep(timeoutInteval);
}while(timeoutWorker.isAlive());
System.out.println("<<<<<<<<<<####>>>>>>>>>>> Timeout Block Executed Within "+collectIntervals+" Milli Seconds.");
}
/**
* @return the timeoutInteval
*/
public long getTimeoutInteval() {
return timeoutInteval;
}
/**
* @param timeoutInteval the timeoutInteval to set
*/
public void setTimeoutInteval(long timeoutInteval) {
this.timeoutInteval = timeoutInteval;
}
}
예 :
try {
TimeoutBlock timeoutBlock = new TimeoutBlock(10 * 60 * 1000);//set timeout in milliseconds
Runnable block=new Runnable() {
@Override
public void run() {
//TO DO write block of code
}
};
timeoutBlock.addBlock(block);// execute the runnable block
} catch (Throwable e) {
//catch the exception here . Which is block didn't execute within the time limit
}