2016-09-10 4 views
0

나는 다음과 같은 상황의 해결책을 찾고 있었다. 나는 Callable의 HashSet을 가지고 있었고이 집합을 집행자에게 병렬 실행을 위해 제출할 것이다. 제출 된 작업이 완료 되 자마자 나는 새로운 Callable을 executor에게 할당 할 수 있어야합니다.집행자에게 과제를 계속 제출하는 방법

이 코드를 사용해 보았지만 executor.invoke를 사용하면 Executor는 모든 작업이 완료 될 때까지 기다렸다가 executor.submit을 사용하면 작업이 순차적으로 완료됩니다. 도움이 될 것입니다. 후속 작업에 submit()를 호출하기 전에 당신이 미래에 get()를 호출하기 때문에

package poc.threading; 

import java.util.HashSet; 
import java.util.List; 
import java.util.concurrent.Callable; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.Future; 

public class ConcurrencyPoC_UsingExecutor_GetFreeThread { 

    public static void main(String[] args) { 
     // TODO Auto-generated method stub 

     executor(); 
    } 


    public static void executor() 
    { 
     try{ 

      ExecutorService ex = Executors.newCachedThreadPool(); 

      //create a set with all callables task 
      HashSet<Callable<Object>> callables = new HashSet<>(); 
      callables.add(task1()); 
      callables.add(task2()); 
      callables.add(task3()); 
      callables.add(task4()); 

      //executes all task together but executor waits for completion of all tasks 

      List<Future<Object>> fu = ex.invokeAll(callables); 
      for(int i=0; i<fu.size(); i++) 
      { 
       System.out.println(fu.get(i).get() + " , " + Thread.currentThread().getName().toString()); 
      } 

      //executes tasks sequentially 
      for(Callable<Object> task : callables) 
      { 
       Future<Object> future = ex.submit(task); 
       System.out.println(future.get() + " , " + Thread.currentThread().getName().toString()); 
      } 
      ex.shutdownNow(); 
     } 
     catch(Exception e) 
     { 
      e.printStackTrace(); 
     } 
    } 


    public static Callable<Object> task1() throws InterruptedException 
    { 
     return new Callable<Object>() { 

      @Override 
      public Object call() throws Exception { 

       int count = 0; 
       while(count < 3) 
       { 
        System.out.println("****** SLEEP TASK1 ******* "+count); 
        Thread.sleep(500); 
        count ++; 
       } 
       return "Sleep Task Of 500 Completed"; 
      } 
     }; 
    } 


    public static Callable<Object> task2() throws InterruptedException 
    { 
     return new Callable<Object>() { 

      @Override 
      public Object call() throws Exception { 

       int count = 0; 
       while(count < 6) 
       { 
        System.out.println("****** SLEEP TASK2 ******* "+count); 
        Thread.sleep(300); 
        count ++; 
       } 
       return "Sleep Task Of 300 Completed"; 
      } 
     }; 
    } 


    public static Callable<Object> task3() throws InterruptedException 
    { 
     return new Callable<Object>() { 

      @Override 
      public Object call() throws Exception { 

       int count = 0; 
       while(count < 2) 
       { 
        System.out.println("****** SLEEP TASK3 ******* "+count); 
        Thread.sleep(1000); 
        count ++; 
       } 
       return "Sleep Task Of 1000 Completed"; 
      } 
     }; 
    } 

    public static Callable<Object> task4() throws InterruptedException 
    { 
     return new Callable<Object>() { 

      @Override 
      public Object call() throws Exception { 

       int count = 0; 
       while(count < 4) 
       { 
        System.out.println("****** SLEEP TASK4 ******* "+count); 
        Thread.sleep(600); 
        count ++; 
       } 
       return "Sleep Task Of 1000 Completed"; 
      } 
     }; 
    } 
} 
+0

문제는 분명하지 않습니다. 코드의 일부분에 작업이 완료되었음을 알리고 싶다면 옵저버 패턴을 사용하고 리스너를 작업에 추가 할 수 있습니다. –

답변

1

당신의 작업은 두 번째 예에서 순차적으로 실행하는 이유입니다. get보다 먼저 submit을 모두 수행하면 병렬로 실행됩니다.

서로 다른 작업을 찾고있는 경우 CompletableFuture 클래스를 살펴보십시오. 이러한 유형의 미래는 처음 시작되면 다른 작업을 시작할 수있게 해줍니다.

CompletableFuture<Object> task1 = CompletableFuture.supplyAsync(() -> task1(), ex); 
CompletableFuture<Object> task2 = task1.thenApplyAsync(task1Result -> task2(), ex);