2015-10-11 23 views
8

Tôi muốn triển khai xử lý không đồng bộ của mình với scalaz.concurrent.Task. Tôi cần một chức năng (Task[A], Task[B]) => Task[(A, B)] để trả về một nhiệm vụ mới mà làm việc như sau:Cách soạn hai Tác vụ song song để hủy một tác vụ nếu một tác vụ khác không thành công?

  • chạy Task[A]Task[B] song song và chờ đợi kết quả;
  • nếu một trong các tác vụ không thành công thì hủy giây thứ hai và chờ cho đến khi nó kết thúc;
  • trả về kết quả của cả hai tác vụ.

Bạn sẽ triển khai chức năng như thế nào?

+0

Có một vài điều khác nhau _cancel_ có thể có nghĩa là ở đây. Bạn chỉ muốn tính toán thất bại nhanh? Sau đó, một cái gì đó như 'cả hai 'trên' Nondeterminism' sẽ làm việc. Nếu bạn cũng muốn tránh các chu kỳ lãng phí (hoặc bạn muốn hoàn tác các tác động của tính toán vẫn đang chạy) nó sẽ phức tạp hơn. –

+0

Có, tôi chỉ muốn tính toán thất bại nhanh chóng ngay bây giờ. – Michael

Trả lời

3

Như tôi đã đề cập ở trên, nếu bạn không quan tâm đến việc dừng tính toán không thành công, bạn có thể sử dụng Nondeterminism. Ví dụ:

import scalaz._, scalaz.Scalaz._, scalaz.concurrent._ 

def pairFailSlow[A, B](a: Task[A], b: Task[B]): Task[(A, B)] = a.tuple(b) 

def pairFailFast[A, B](a: Task[A], b: Task[B]): Task[(A, B)] = 
    Nondeterminism[Task].both(a, b) 

val divByZero: Task[Int] = Task(1/0) 
val waitALongTime: Task[String] = Task { 
    Thread.sleep(10000) 
    println("foo") 
    "foo" 
} 

Và sau đó:

pairFailSlow(divByZero, waitALongTime).run // fails immediately 
pairFailSlow(waitALongTime, divByZero).run // hangs while sleeping 
pairFailFast(divByZero, waitALongTime).run // fails immediately 
pairFailFast(waitALongTime, divByZero).run // fails immediately 

Trong mọi trường hợp, ngoại trừ người đầu tiên tác dụng phụ trong waitALongTime sẽ xảy ra. Nếu bạn muốn cố gắng ngừng tính toán đó, bạn cần sử dụng một cái gì đó như runAsyncInterruptibly của Task.

2

Có một quan niệm lạ giữa các nhà phát triển java rằng bạn không nên hủy các tác vụ song song. Họ cam kết Thread.stop() và đánh dấu nó không còn được dùng nữa. Nếu không có Thread.stop() bạn không thể hủy bỏ tương lai. Tất cả những gì bạn có thể làm là gửi một số tín hiệu đến tương lai hoặc sửa đổi một số biến được chia sẻ và tạo mã bên trong tương lai để kiểm tra định kỳ. Vì vậy, tất cả các thư viện cung cấp tương lai có thể đề xuất cách duy nhất để hủy bỏ tương lai: làm điều đó hợp tác.

Tôi đang gặp phải sự cố tương tự ngay bây giờ và đang ở giữa việc viết thư viện của riêng tôi cho tương lai có thể bị hủy. Có một số khó khăn nhưng chúng có thể được giải quyết. Bạn không thể gọi Thread.stop() ở bất kỳ vị trí tùy ý nào. Chủ đề có thể thực hiện cập nhật các biến được chia sẻ. Khóa sẽ được gọi lại bình thường, nhưng bản cập nhật có thể bị dừng lại một nửa, ví dụ: chỉ cập nhật một nửa giá trị gấp đôi, v.v. Vì vậy, tôi giới thiệu một số khóa. Nếu luồng nằm trong trạng thái được bảo vệ, thì nó sẽ bị Thread.stop() giết ngay bây giờ nhưng với việc gửi một thông báo cụ thể. Trạng thái được bảo vệ được coi là luôn luôn rất nhanh để chờ đợi. Tất cả thời gian khác, ở giữa tính toán, luồng có thể được dừng lại một cách an toàn và thay thế bằng một cái mới. Vì vậy, câu trả lời là: bạn không nên muốn hủy bỏ tương lai, nếu không bạn là kẻ dị giáo và không ai trong cộng đồng java sẽ cho bạn mượn một tay sẵn sàng. Bạn nên xác định bối cảnh thực thi của riêng bạn có thể giết chủ đề và bạn nên viết thư viện tương lai của riêng mình để chạy theo ngữ cảnh này

+0

Ngôn ngữ/môi trường nào có thể hủy bỏ chủ đề không hợp tác? Một tìm kiếm nhanh cho thấy rằng không phải C# (http://stackoverflow.com/questions/14131608/how-to-terminate-a-thread-in-c), C++ 11 (http://stackoverflow.com/questions/ 12207684/how-do-i-terminate-a-thread-in-c11) hoặc Python (http://stackoverflow.com/questions/323972/is-there-any-way-to-kill-a-thread-in -python) thì không. – thoredge

+0

bình thường c hoặc C++.Tất nhiên nó không thể được thực hiện theo cách di động như bạn trỏ, nhưng mọi hệ điều hành đều có các lời gọi API thread riêng của nó có thể được sử dụng bởi ứng dụng c hoặc C++. Không di động là bình thường đối với mã c/C++ – ayvango

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