2016-09-10 3 views
0

Я искал решение такой ситуации, как: У меня есть HashSet из Callables, и я отправляю этот набор исполнителю для параллельного выполнения. Теперь я хочу, чтобы как только любая поставленная задача была завершена, я должен был бы назначить нового Callable для исполнителя.Как сохранить задание исполнителю

Я пробовал этот код, но при этом, если я использую executor.invoke, то Executor ждет, пока все задачи не будут завершены, и если я буду использовать executor.submit, то задачи будут завершены последовательно. Любая помощь будет оценена по достоинству.

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() на последующих задач. Если вы делаете все свои submit s перед любыми get с, они будут работать параллельно.

Если вы ищете задачи в зависимости друг от друга, взгляните на класс CompletableFuture. Этот тип будущего позволит вам начать еще одно задание с самого начала:

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