2012-08-10 23 views
6

Tôi đang cố gắng hiểu cách Callable có thể trả lại giá trị khi nó chạy trên một chuỗi khác.Làm thế nào để một công việc có thể gọi dưới mui xe? Làm cách nào để một đối tượng có thể gọi trả về một giá trị?

Tôi đang tìm trong các lớp học Executors, AbstractExecutorService, ThreadPoolExecutorFutureTask, tất cả có sẵn trong gói java.util.concurrent.

Bạn tạo đối tượng ExecutorService bằng cách gọi một phương thức trong Executors (ví dụ: newSingleThreadExecutor()). Sau đó, bạn có thể chuyển đối tượng có thể gọi với ExecutorService.submit(Callable c).

Vì phương pháp call() được chạy bởi chuỗi được cung cấp bởi ExecutorService, đối tượng trả về "nhảy" quay lại chuỗi đang gọi?

Nhìn vào ví dụ đơn giản này:

1 ExecutorService executor = Executors.newSingleThreadExecutor(); 
2 public static void main(String[] args) { 
3  Integer i = executor.submit(new Callable<Integer>(){ 
4   public Integer call() throws Exception { 
5    return 10; 
6   } 
7  }).get(); 
8  System.out.print("Returns: " + i + " Thread: " + Thread.currentThread.getName()); 
9  // prints "10 main" 
10 } 

Làm thế nào là nó có thể là số nguyên trong phương pháp gọi, được điều hành bởi một chủ đề riêng biệt, được trả lại cho các đối tượng Integer (hàng 3) để nó có thể được in bởi câu lệnh System.out trong chủ đề chính (dòng 7)?

Không thể chạy chuỗi chính trước khi ExecutorService chạy chủ đề của nó sao cho các bản in System.out statement không có giá trị?

+0

Có một vài lỗi biên dịch trong mã này; ví dụ, 'executor.submit' trả về một tương lai, không phải là một số nguyên, và' currentThread' là một phương thức cần được gọi. Nếu bất cứ ai quan tâm để xem một ví dụ làm việc, hãy xem http://ideone.com/myoMB –

+0

Xin lỗi, tôi đã viết mã đó bằng tay. :-) Tôi sẽ xem xét ví dụ của bạn. – Rox

+0

Ồ không sao cả, tôi chỉ cố gắng giúp đỡ thôi. Đó là một câu hỏi hay. +1 –

Trả lời

8

Làm thế nào là nó có thể là số nguyên trong phương pháp gọi, được điều hành bởi một chủ đề riêng biệt, được trả lại cho các đối tượng Integer

ExecutorService.submit(...) không không trở lại đối tượng từ call() nhưng nó trả lại một Future<Integer> và bạn có thể sử dụng phương thức Future.get() để nhận đối tượng đó. Xem mã ví dụ bên dưới.

Không thể chạy chuỗi chính trước khi ExecutorService chạy chuỗi, sao cho lệnh System.out in rỗng?

Không, phương pháp get() trong tương lai sẽ đợi cho đến khi hoàn thành công việc. Nếu call() trả về null thì get() nếu không nó sẽ trả lại (và in) 10 được bảo đảm.

Future<Integer> future = executor.submit(new Callable<Integer>(){ 
    public Integer call() throws Exception { 
     return 10; 
    } 
}); 
try { 
    // get() waits for the job to finish before returning the value 
    // it also might throw an exception if your call() threw 
    Integer i = future.get(); 
    ... 
} catch (ExecutionException e) { 
    // this cause exception is the one thrown by the call() method 
    Exception cause = e.getCause(); 
    ... 
} 
+0

Cảm ơn bạn đã trả lời! Việc chờ đợi xảy ra ở đâu? Nó phải là một số đồng bộ hóa để các thread gọi (ví dụ chủ đề chính) có thể chờ cho ExecutorService hoàn thành nhiệm vụ của nó. Tôi đã tìm trong FutureTask và trong ThreadPoolExecutor và cannod thấy đồng bộ hóa như vậy. – Rox

+0

Liệu nó có hoạt động như thế này hay không, rằng luồng chính đi vào phương thức 'Future.get()' trước khi ExecutorService đi vào phương thức 'RunnableFuture.run()', nhưng phương thức chính phải đợi cho ExecutorService hoàn thành chạy () và khi nó có, nó sẽ thông báo chuỗi chính để tiếp tục với phương thức get()? – Rox

+2

'Future.get()' hiện đang chờ đợi. Bên trong 'FutureTask' tôi tin rằng' obtainSharedInterruptibly (0) 'và sau đó gọi' doAcquireSharedInterruptibly (...) 'thực hiện đồng bộ và chờ đợi. Quá trình đồng bộ hóa được thực hiện với 'volatile'. – Gray

4

Có một cái nhìn về ExecutorService.submit() phương pháp:

<T> Future<T> submit(Callable<T> task): nộp một nhiệm vụ giá trị gia trở về để thực hiện và trả về một tương lai đại diện cho các kết quả đang chờ giải quyết của nhiệm vụ. Phương thức get của Future sẽ trả về kết quả của nhiệm vụ sau khi hoàn thành thành công. Nếu bạn muốn chặn ngay lập tức chờ đợi cho một nhiệm vụ, bạn có thể sử dụng công trình xây dựng có dạng result = exec.submit(aCallable).get();


Q. Isn't nó có thể cho các chủ đề chính được chạy trước khi ExecutorService có chạy chủ đề của nó, sao cho câu lệnh System.out in null?

->Future<T>.get() Waits nếu cần thiết cho việc tính toán để hoàn thành, và sau đó lấy kết quả của nó.

+0

Cảm ơn bạn đã trả lời. Nhìn vào câu hỏi của tôi với câu trả lời của Gray. Đồng bộ hóa diễn ra ở đâu để luồng chính có thể đợi cho ExecutorService hoàn thành nhiệm vụ của nó? – Rox

Các vấn đề liên quan