2015-04-21 11 views
9

Sử dụng ngữ cảnh thực thi ngầm định mặc định trong Scala, mỗi tương lai mới sẽ được tính toán trên một chuỗi chuyên dụng hay tính toán được phân chia cho nhiều luồng trong nhóm luồng?Tương lai có được thực hiện trên một chuỗi không? (Scala)

Tôi không biết điều này có hữu ích hay không, nền tảng cho câu hỏi này là tôi muốn thực hiện nhiều hoạt động đồng thời bằng cách sử dụng API HtmlUnit. Để làm điều này, tôi sẽ bọc mỗi cá thể WebClient mới trong tương lai. Vấn đề duy nhất là lớp WebClient không phải là luồng an toàn, vì vậy tôi lo lắng rằng nó có thể bị hỏng và gửi đến các luồng khác nhau.

Trả lời

14

Một tương lai được thực hiện trên một chuỗi duy nhất. Một số tương lai có thể được thực hiện trên một số chủ đề. Vì vậy, không nhiều hơn về tương lai có thể chiếm một thread đồng thời.

Cách hoạt động? Khi bạn tạo ra một tương lai, điều đó có nghĩa là bạn đã gửi nhiệm vụ tới nhóm chủ đề của mình - nhiệm vụ này không thể song song hoàn toàn do đó nó được thực hiện trên một luồng chỉ. Một hoặc nhiều nhiệm vụ được gửi đến nhóm đang được đưa vào hàng đợi của nhóm, do đó, người thực thi sẽ thực hiện các nhiệm vụ từ hàng đợi đó từng người một và chạy từng công việc trên một số chủ đề được chọn ngẫu nhiên (hoặc cố ý). Vì vậy, một số tương lai có thể nhận được một số chủ đề.

Giới thiệu về đối tượng được chia sẻ - cách duy nhất để thực thi thao tác an toàn cho đối tượng được chia sẻ giữa tương lai là sử dụng Executors.newFixedThreadPool(1), nó sẽ chỉ sử dụng một luồng cho toàn bộ nhóm. Một giải pháp khác - là sao chép đối tượng đó cho mọi tương lai. Sử dụng diễn viên (làm cho đối tượng được chia sẻ của bạn là trạng thái của diễn viên) nên là lựa chọn tốt nhất.

Nếu bạn sử dụng một đối tượng cho mỗi tương lai - mọi thứ sẽ ổn.

Lưu ý: Trình xử lý của tương lai, như Future{ ... }.map(handler) có thể được thực hiện trong chuỗi khác với chính tương lai, nhưng nó thực sự tạo một số khác Future để nhận kết quả. Tương tự cho flatMap. Chính xác hơn, họ sử dụng onComplete mà tạo ra CallbackRunnable để khởi động xử lý (có thể trong chủ đề khác nhau) sau khi thành công cũ tương lai của - callback này chỉ hoàn thành trong tương lai newely tạo, vì vậy vẫn "không có nhiều hơn một thread mỗi tương lai"

+0

Cảm ơn! Đó chính xác là thông tin tôi đang tìm kiếm. Chỉ cần một câu hỏi tiếp theo nhanh - có lợi thế nào khi gửi nhiều tương lai cho một newFixedThreadPool chỉ với một luồng không? Có thể tính toán đồng thời trên một sợi đơn không? –

+0

Không có lợi thế về hiệu suất nào cả. Điều duy nhất nó có thể cung cấp cho bạn là API asynchoronous (nộp nhiều nhiệm vụ + đăng ký hoàn thành của họ). Bạn cũng có thể tạo ra một số hồ bơi cho các loại tương lai khác nhau, nhưng các diễn viên là tốt hơn cho điều đó. – dk14

+1

Tạo một 'ExecutionContext' từ' Executors.newFixedThreadPool (1) 'với' implicit val executionContext = ExecutionContext.fromExecutorService (Executors.newFixedThreadPool (1)) '. – jpcooper

-1

Một Future[+T] có thể không đảm bảo rằng nó sẽ được hoàn thành trên cùng một chủ đề nếu nó bao gồm nhiều tương lai. Điều đó nói rằng, nó không có nghĩa là bạn sẽ nhận được một ngoại lệ sửa đổi đồng thời hoặc một cái gì đó dọc theo những dòng đó. Bạn vẫn có thể nhận được mã không đồng bộ để thực thi tuần tự, trong trường hợp đó nó sẽ an toàn.

Đối với câu hỏi thứ hai của bạn, miễn là bạn có một phiên bản cho mỗi tương lai, bạn không nên có bất kỳ vấn đề tương tranh nào.

+0

nếu bằng cách sáng tác, bạn có ý nghĩa giống như ['Future.sequence'] (https://github.com/scala/scala/blob/2.11.x/src/library/scala/concurrent/Future.scala) - chúng chỉ tạo một tương lai thành công mới với cơ thể trống rỗng (do đó, nó thực hiện hư không ở tất cả) và sau đó thêm xử lý (whichadd xử lý để tương lai trong thành phần). Vì vậy, tương lai chính nó được thực hiện trong chủ đề duy nhất; tuy nhiên các trình xử lý ('Tương lai.Bản đồ') có thể được thực hiện ở những cái khác nhau, nhưng mỗi trình xử lý mới trả về một * khác nhau * tương lai – dk14

+0

Vì vậy, trình tự chỉ tạo ra một số tương lai mới, nhưng không có * đơn * tương lai nào từ chúng có thể được gán cho nhiều hơn một luồng. – dk14

+0

Tôi đang đề cập đến việc sử dụng flatMap hoặc để hiểu về tương lai. –

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