2009-08-24 3 views
7

나는 정기적 인 작업을 예약하기 위해 java.util.Timer을 사용하고 있습니다. 어느 시점에서 종료하고 싶습니다. 이 완료 될 때까지 기다리십시오.타이머가 Java에서 완료되기를 기다리는 중

Timer.cancel()은 향후 작업이 실행되지 않도록합니다. 현재 작업이 실행 중이 아닌지 확인 (또는 대기중인 경우 대기).

외부 동기화 메커니즘을 도입 할 수는 있지만 모든 사례를 어떻게 처리 할 수 ​​있는지는 알 수 없습니다. 예를 들어, 작업 내에서 일부 모니터를 동기화하는 경우, 작업이 방금 실행을 시작했지만 모니터를 가져 가지 않았을 때 여전히 그 경우를 놓치고 있습니다.

현재 실행중인 작업을 포함하여 모든 작업이 실제로 완료 될 때까지 기다리는 것이 좋습니다.

답변

18

정기적 인 작업을 예약하는 데 타이머 대신 ScheduledExecutorService을 사용하는 것이 좋습니다. ScheduledExecutorService는 보류중인 모든 작업을 실행하는 shutdown() 메서드를 제공합니다. 그런 다음 awaitTermination()을 호출하여 shutdown()이 완료 될 때까지 기다릴 수 있습니다. 다음과 같은

+0

일을 도움이 될 수 있습니다. 또는 어떤 이유로 Timer를 사용해야하는 경우 조건 (http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/locks/)을 사용할 수 있습니다. Condition.html)을 사용하여 이벤트 (예 : 예약 된 작업 완료)의 두 스레드를 동기화합니다. –

+2

예, Effective Java (Second ed)의 68 번 항목은 ScheduledThreadPoolExecutor를 Timer를보다 유연하게 대체 할 것을 권장합니다. 권장 사례가 요구됨에 따라이를 언급하는 데 +1했습니다. – Jonik

+0

그래, 나는 그 책을 정말로 읽어야한다. – ripper234

0

무언가가 당신의 needs-

import java.util.Timer; 
import java.util.TimerTask; 

public class TimerGracefulShutdown { 
    public static void main(String[] args) throws InterruptedException { 
     //This is a synchronization helper class 
     SyncHelper syncHelper = new SyncHelper(); 

     TimerManager myTimerManager = new TimerManager(syncHelper); 

     //Try stopping timer after 5 seconds (it wont stop until the 30 seconds sleep of timertask does not finish) 
     Thread.currentThread().sleep(5000); 
     System.out.println("Going to stop my timer now"); 
     myTimerManager.stopTimer(); 
     System.out.println("Cancelled timer"); 
    } 
} 

class TimerManager { 

    SyncHelper syncHelper; 
    Timer timer; 

    public TimerManager(SyncHelper syncHelper) { 
     this.syncHelper = syncHelper; 
     startTimer(); 
    } 

    private void startTimer() { 
     timer = new Timer(true); 
     TimerTask myTask = new MyTimerTask(syncHelper); 
     timer.scheduleAtFixedRate(myTask, 0, 100000); 
    } 

    public void stopTimer() { 
     try { 
      syncHelper.testAndSetOrReset("acquire"); 
     } catch(Exception e) { 
      e.printStackTrace(); 
     } 

     //Shutdown the timer here since you know that your timertask is not executing right now. 
     timer.cancel(); 
     try { 
      syncHelper.testAndSetOrReset("release"); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

} 

class MyTimerTask extends TimerTask { 

    private SyncHelper syncHelper; 

    public MyTimerTask(SyncHelper syncHelper) { 
     this.syncHelper = syncHelper; 
    } 

    public void run() { 
     try { 
      syncHelper.testAndSetOrReset("acquire"); 
     } catch (Exception e1) { 
      e1.printStackTrace(); 
     } 

     System.out.println("Over here"); 
     try { 
      Thread.currentThread().sleep(30000); 
     } catch(Exception e) { 

     } 
     System.out.println("Done sleeping"); 

     //Finally release the helper. 
     try { 
      syncHelper.testAndSetOrReset("release"); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

} 

class SyncHelper { 

    private int index = 0; 

    public synchronized void testAndSetOrReset(String command) throws Exception { 

     if("acquire".equals(command)) { 
      if(index == 1) { 
       wait(); 
      } 
      index++; 
     } else if("release".equals(command)) { 
      index--; 
      notifyAll(); 
     } 
    } 
} 
+0

당신은'Thread.sleep (. ..)'Thread.currentThread(). sleep (...) 대신 정적 메서드이기 때문에. 당신의 코드는'someOtherThread.sleep (...)'을하도록 유혹 할 수 있습니다. – newacct

관련 문제