2013-07-30 3 views
5

스레드가있어 영원히 계속 작동 할 수 있습니다. 따라서 일정한 시간이 지나면 실행을 멈추고 마침내 방법으로 이동하여 정리를 수행 한 다음 죽을 수 있습니다. 이 작업을 안전하게 수행하려면 어떻게해야합니까? 감사.특정 시간이 지난 후에 마지막으로 스레드를 이동하십시오.

이 작업을 수행하는 방법에 대한 저의 첫 번째 생각은 자식 스레드를 만들고 해당 수면을 가지고 정리를 수행하는 것이 었습니다. 하지만 부모 스레드가 여전히 실행하려고 할 때 오류를 출력 할 수 없습니다.

+0

이 스레드에는 최상위 루프가 있습니까? 스레드가 멈추더라도 반복적으로 도달하는 코드가 있습니까? 스레드가 작동하기 전에 얼마나 많은 시간 동안 루프가 반복되는지 예측할 수 있습니까? –

+0

이상적으로, 스레드가 주기적으로 검사하는 플래그가 있어야합니다. 플래그가 설정되어 있으면 스레드가 순서대로 작업을 종료해야합니다. – Aurand

+0

루프 등이 없습니다. 스레드가 데이터를 보내지 만 데이터를 보내는 데 너무 오래 걸리는 경우 종료해야합니다. 한 줄의 코드에 붙어 있으면 주기적으로 검사 할 수 있습니까? – user760220

답변

3

코드를 리팩터링하여 Callable에 넣고 ExecutorService를 사용하여 미래를 얻으십시오. 그런 다음 timeout을 사용하여 get을 사용하십시오. 그러면 timeoutException이 throw됩니다. 전체 예제는 https://stackoverflow.com/a/2275596/53897을 참조하십시오.

+0

나는 미래에 대해 완전히 잊었다. +1 –

+1

활성 스레드를 죽게하지 않습니다. 'Future.get (long, TimeUnit)'을 호출 한 대기 스레드 만 다시 시작됩니다. 작업이 계속 실행됩니다. – yair

+0

그런 다음 executor에게 시스템 종료를 알리십시오. –

0

차단 호출에 대한 시간 제한을 설정해야합니다. 시간 제한이 없으면 전화를 추상화하고 시간을 초과하십시오.

작업을 완료 상태로 폴링하는 스레드를 1 개 생성하고 초과 된 값을 초과하면 작업을 종료 할 수 있습니다. 작업 자체는 여전히 또 다른 스레드를 필요로합니다. 나는 staleness 값을 가진 작업을 만들어서이 작업을 수행 할 것입니다. 정기적으로 모든 작업을 폴링하고, 오래된 경우 취소하십시오.

0

제안 1 : wait() 문을 사용하여 try 블록에 코드를 삽입하면 interruptedException을 catch하여 마지막으로 수행 할 수 있습니다. 다른 스레드는 notify() 또는 notifyAll()을 보내 상황에 따라 스레드를 중단해야 할 때마다 인터럽트를 발생시켜야합니다.

제안 2 : 저는 자바 초보자에 불과하지만 스레드가 걸려 넘어지면 try/finally 블록 내에 사용자 정의 예외를 throw 할 수 있어야합니다.

+0

Java 5에 대한 동시 추가 기능이 흥미로울 수 있습니다. 스레드를 직접 사용하는 것은 100 % 올바르게 수행하기 어렵습니다. –

0

(1)

가장 좋은 방법은 시간 초과로 데이터를 전송하는 것입니다. 이 적용되지 않는 경우 이러한 구성을 노출하지 않습니다 사용하고있는 API가, 두 번째 가장 좋은 방법은 인터럽트 API를 사용하는 것 때문에

try { 
    mySendingDataLibraryApi.sendData(data, timeout /*, timeUnit */); 
     // some new APIs enable also to configure the time unit of the required timeout. 
     // Older APIs typically just use milliseconds. 
} catch (TimeoutException e) { 
    doCleanup(); // your cleanup method. 
} 

(2)

처럼 보일 것이다 sendData 메서드를 호출하고 실행 스레드를 인터럽트합니다. 이는 이러한 인터럽트 가능한 API가 제공된다는 사실에 의존합니다.

class MySendingDataRunnable implements Runnable {  
    @Override 
    public void run() { 
     try { 
      mySendingDataLibraryApi.sendDataInterruptibly(data); 
     } catch (InterruptedException e) { 
      doCleanup(); // your cleanup method. 
      // here either re-throw InterruptedExecption 
      // or restore the interrupted state with Thread.currentThread().interrupt(); 
     } 
    } 
} 

: 시간 형 방법은 API가 제공되지 않은 경우 나는 이러한 방법의 존재에 많이 포함되지 것입니다 ... 어쨌든, 작업을 실행하는 스레드의 코드는 같을 것이다

final ExecutorService executor = Executors.newSingleThreadExecutor(); 
final Future<?> future = executor.submit(new MySendingDataRunnable()); 
try { 
    final Object noResult = future.get(60, TimeUnit.SECONDS); // no result for Runnable 
} catch (InterruptedException e) { 
    // here again either re-throw or restore interupted state 
} catch (ExecutionException e) { 
    // some applicative exception has occurred and should be handled 
} catch (TimeoutException e) { 
    future.cancel(true); // *** here you actually cancel the task after time is out 
} 

(3 : 호출자의 코드는 스레드, true로 설정 mayInterruptIfRunning 인수 작업을 원하는 시간을 기다린 취소하기 위해, 자사의 Future<?> submit(Runnable task) 방법 리턴 한 ExecutorServiceFuture 인스턴스를 사용한다)

사용하는 API가 이러한 기능 (시간 지정/중단 방법)을 제공하지 않는 경우 창의력을 사용해야합니다! 이 한 줄의 코드를 차단하려면 일부 리소스에서 을 차단해야합니다. 이 자원에 접근하여 종료하거나 종료하여 암시 적으로 작업이 종료되도록하십시오.일반적인 예는 네트워크 연결을 닫는 것입니다.


참고 : 위의 솔루션은 실제로 작업을 취소하고 추가 작업에 대한 스레드를 확보하는 방법을 제공합니다. 스레드가 여전히 살아있을 수 있습니다. 스레드를 죽이는 것은 일반적으로 작업이 완료되거나 실패 할 때 수행하는 작업이 아닙니다. 다시는 실행되지 않아야 할 특정 작업에 대한 스레드를 만들었 으면 좋을 것입니다. 그러한 경우 위의 ExecutorService을 사용하고 해당 shutdownNow() 메소드를 호출합니다. 그리고 심지어 shutdownNow()에만 최선의 노력을하고 일반적으로 인터럽트 될하기 위해 실제 작업에 따라 달라집니다 ...

Here's a detailed article (그럼에도 불구하고 다소 오래된하지만).

관련 문제