2012-10-24 3 views
0

3 개의 스레드가 동시에 작업을 수행하고 일정 기간 (10 초마다 실행 됨)에 예약 된 작업을 수행하는 스레드가 필요합니다. 하지만 3 스레드가 예약 된 작업을 한 번만 실행하고이 스레드가 종료되도록하고 싶을 때가 있습니다. 이 스레드를 구현하는 가장 좋은 방법은 무엇입니까? ExecutorService 인터페이스는 이에 적합합니다. 여기다른 스레드가 완료된 후 주기적 작업 일정 예약

답변

3

난 그냥 작성한 것으로 예 : 여기

import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.ScheduledFuture; 
import java.util.concurrent.TimeUnit; 

public class Example { 

    public static void main(String[] args) throws InterruptedException { 
     ScheduledFuture future = Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new MyScheduledTask(), 0, 10, TimeUnit.SECONDS); 
     ExecutorService executor = Executors.newFixedThreadPool(3); // pool composed of 3 threads 
     for (int i = 0; i < 3; i++) { 
      // for the example assuming that the 3 threads execute the same task. 
      executor.execute(new AnyTask()); 
     } 
     // This will make the executor accept no new threads 
     // and finish all existing threads in the queue 
     executor.shutdown(); 
     // expect current thread to wait for the ending of the 3 threads 
     executor.awaitTermination(Long.MAX_VALUE, TimeUnit.TimeUnit.NANOSECONDS); 
     future.cancel(false); // to exit properly the scheduled task 
     // reprocessing the scheduled task only one time as expected 
     new Thread(new ScheduledTask()).start(); 

    } 


} 

class MyScheduledTask implements Runnable { 
    @Override 
    public void run() { 
     //Process scheduled task here 
    } 
} 

class AnyTask implements Runnable { 
    @Override 
    public void run() { 
     //Process job of threads here 
    } 
} 
+0

작동합니다. 사실 내 솔루션의 문제점은'sheduler.shutdown()'을'executor.aWaitTermination()'의 try 블록 안에 넣었다는 것입니다. ScheduledExecutorService를 사용하여 스케줄러를 생성했습니다. 그 해결책에 대해 어떻게 생각하세요? – Manos

+0

@Manos Samatas 흠, 게시물을 업데이트하여 코드를 표시 할 수 있습니까? – Mik378

+0

@Manos Samatas 어쨌든'executor.aWaitTermination()'은 논리적으로'sheduler.shutdown()'뒤에 있어야합니다. 그렇지 않으면 현재 스레드가 최대 시간 동안 대기 한 다음 풀이 종료됩니다 ... 공연. 게다가, 현재 쓰레드가 다른 쓰레드의 종료를 기다리기 전에 그 쓰레드를 계속해서 수행하지 못하게하는 것은 아무것도 없다. – Mik378

1

는 작업을 하나씩 실행하는주기적인 작업 스케줄러의 예입니다. 작업 스케줄러는 작업 배열을 가져 와서 별도의 스레드에서 지정된 간격 후에 각 작업을 종료합니다. 20 초 후에 주 스레드는 스케줄러를 종료하고 대기중인 모든 작업을 중지합니다.

import java.util.Arrays; 
import java.util.Iterator; 
import java.util.List; 
import java.util.concurrent.CancellationException; 
import java.util.concurrent.ExecutionException; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.ScheduledExecutorService; 
import java.util.concurrent.ScheduledFuture; 
import java.util.concurrent.TimeUnit; 

public class Example { 

    class ScheduledRepeatingTask implements Runnable { 
     final ScheduledExecutorService scheduler = Executors 
       .newScheduledThreadPool(1); 

     List<Runnable> taskCollection; 
     Iterator<Runnable> taskIterator; 

     Runnable getCancelRunnable(final ScheduledFuture<?> future) { 

      Runnable cancelFuture = new Runnable() { 
       public void run() { 
        future.cancel(true); 
       } 
      }; 
      return cancelFuture; 
     } 

     public ScheduledRepeatingTask(Runnable[] tasks) { 
      super(); 
      taskCollection = Arrays.asList(tasks); 
      taskIterator = taskCollection.iterator(); 
     } 

     public void shutdownScheduler() throws InterruptedException { 
      scheduler.shutdown(); 
      boolean execTerminated = scheduler.awaitTermination(5, 
        TimeUnit.SECONDS); 

      if (!execTerminated) { 
       scheduler.shutdownNow(); 
      } 
     } 

     public boolean isShutdown(){    
      return scheduler.isShutdown(); 
     } 

     public void scheduleRepeatingTask(ScheduledFuture<?> future, 
       ScheduledFuture<?> futureCancel) { 

      try { 
       futureCancel.get(); 
       future.get(); 

      } catch (CancellationException e) { 
       System.out.println("cancelled."); 
      } catch (ExecutionException e) { 
       Throwable exp = e.getCause(); 
       if (exp instanceof RuntimeException) { 
        System.out.println("failed."); 
        RuntimeException rt = (RuntimeException) exp; 
        throw rt; 
       } 
      } catch (InterruptedException e) { 
       Thread.currentThread().interrupt(); 
      } finally { 
       if (!scheduler.isShutdown() && taskIterator.hasNext()) { 
        future = scheduler.scheduleAtFixedRate(taskIterator.next(), 
          2, 2, TimeUnit.SECONDS); 
        futureCancel = scheduler.schedule(
          getCancelRunnable(future), 5, TimeUnit.SECONDS); 
        scheduleRepeatingTask(future, futureCancel); 

       } 
      } 
     } 

     @Override 
     public void run() { 
      if (!scheduler.isShutdown() && taskIterator.hasNext()) { 
       ScheduledFuture<?> future = scheduler.scheduleAtFixedRate(
         taskIterator.next(), 2, 2, TimeUnit.SECONDS); 
       ScheduledFuture<?> futureCancel = scheduler.schedule(
         getCancelRunnable(future), 5, TimeUnit.SECONDS); 
       scheduleRepeatingTask(future, futureCancel); 
      } 
     } 

    } 

    public static void main(String[] args) throws InterruptedException { 
     Example example = new Example(); 
     ExecutorService executor = Executors.newCachedThreadPool(); 

     Runnable[] tasks = { new Task1(), new Task2(), new Task1() }; 

     ScheduledRepeatingTask scheduledRepeatingTask = example.new ScheduledRepeatingTask(tasks); 

     executor.execute(scheduledRepeatingTask); 

     Thread.sleep(20000); 

     scheduledRepeatingTask.shutdownScheduler(); 

     executor.shutdown(); 

    } 

} 

class Task1 implements Runnable { 
    @Override 
    public void run() { 
     System.out.println("Task 1"); 
    } 
} 

class Task2 implements Runnable { 
    @Override 
    public void run() { 
     System.out.println("Task 2"); 
    } 
}