2013-07-05 83 views
1

在AJAX中,假設我異步提交請求。當reposne返回時,它執行一個回調函數。多線程環境中的java回調函數

在java多線程環境中實現相同的最佳方式是什麼? 即主線程創建一個子線程並提交一個任務,然後子線程返回一個回調函數需要由主線程執行。

這可能嗎?在主線程中,我可以執行wait(),並且在子線程中,我可以執行notify(),但在這種情況下,主線程將等待直到子線程完成。 但在AJAX主線程繼續工作......這就是我想要

回答

1

你可以使用一個ExecutorService做的後臺任務,然後使用的Future方法你回到等待爲結果。例如:

class Main { 
    private static final ExecutorService es = Executors.newCachedThreadPool(); 

    public static void main(final String... args) throws Throwable { 
    List<Future<Integer>> results = new ArrayList<>(); 
    for (int i = 0; i < 10; i++) { 
     results.add(asyncSum(i, i*i)); 
    } 
    // here, in the main thread, you can do whatever you want 
    // while the calculations are performed in background threads 
    // ... 

    // after the main thread finishes what it was doing, it 
    // can process the futures 
    for (final Future<Integer> result : results) { 
     System.out.println(result.get()); 
    } 
    } 

    // this method launches a calculation on a worker thread and immediately 
    // returns a Future, which is a reference to the result of the calculation 
    // once it is completed 
    private static Future<Integer> asyncSum(final int a, final int b) { 
    return es.submit(new Callable<Integer>() { 
     @Override public Integer call() throws Exception { 
     return a + b; 
     } 
    }); 
    } 
} 

在上面的例子中,主線程將阻塞,直到第一次計算完成,然後打印它。然後阻塞,直到第二次計算完成,然後打印等

如果你要打印的結果,因爲它們變得可用(未指定順序),那麼你可以使用一個CompletionService,而是具有結果列表並對其進行迭代,您可以通過完成服務本身通過.take()方法獲得期貨,該方法阻止直到計算完成;或者.poll(),如果存在完成計算,則返回Future;如果存在完成計算,則返回null沒有完成計算 - 這樣你的主線程將永遠不會阻塞。如下示例使用CompletionService。它顯示了永不阻擋的主線程,使用後臺線程進行計算並在結果可用時處理結果:

class Main { 
    public static void main(String[] args) throws Throwable { 
    final ExecutorService es = Executors.newCachedThreadPool(); 
    final CompletionService<Integer> cs = new ExecutorCompletionService<>(es); 

    submitSomeCalculations(cs); 

    while (true) { 
     doMainThreadWork(); 
     processFinishedCalculations(cs); 
    } 
    } 

    private static void submitSomeCalculations(final CompletionService<Integer> cs) { 
    for (int i = 0; i < 10; i++) { 
     submitAsyncSum(cs, i, i * i); 
    } 
    } 

    private static void submitAsyncSum(final CompletionService<Integer> cs, final int a, final int b) { 
    cs.submit(new Callable<Integer>() { 
     @Override public Integer call() throws Exception { 
     Thread.sleep(100 + (long) (Math.random() * 900)); 
     return a + b; 
     } 
    }); 
    } 

    private static void processFinishedCalculations(final CompletionService<Integer> cs) throws ExecutionException, InterruptedException { 
    while (true) { 
     final Future<Integer> result = cs.poll(); 
     if (result == null) { 
     System.out.println("> no finished results..."); 
     break; 
     } else { 
     System.out.println("> result available: " + result.get()); 
     } 
    } 
    } 

    static void doMainThreadWork() { 
    System.out.println("work from main thread..."); 
    } 
}