2013-05-03 28 views
13

Tôi cố gắng để hiểu Scala tương lai đến từ nền Java: Tôi hiểu bạn có thể viết:Scala - tương lai và đồng thời

val f = Future { ... } 

sau đó tôi có hai câu hỏi:

  1. như thế nào trong tương lai này dự kiến ? Tự động?
  2. Trình quản lý lịch sử sẽ sử dụng công cụ lập lịch nào? Trong Java, bạn sẽ sử dụng một người thực thi có thể là một nhóm luồng, v.v.

Hơn nữa, làm cách nào để thực hiện sau một thời gian trễ cụ thể? Cảm ơn

+1

Nếu bạn muốn kiểm soát trực tiếp khi một tương lai sẽ được hoàn thành, bạn nên sử dụng Lời hứa. –

+1

Các lời hứa có một chút khác biệt - về cơ bản chúng là một 'Tương lai' như được thấy từ khung nhìn của người thi hành (tức là một thùng chứa ghi một lần mà nó phải chèn một giá trị vào một thời điểm nào đó). Người gọi/khách hàng không có cách nào để trực tiếp sử dụng 'Lời hứa' để kiểm soát lịch biểu. –

Trả lời

11

Khối Future { ... } là cú pháp đường cho cuộc gọi đến Future.apply (vì tôi chắc chắn bạn biết Maciej), chuyển qua khối mã làm đối số đầu tiên.

Nhìn vào docs for this method, bạn có thể thấy rằng phải mất một ngữ cảnh ngụ ý ExecutionContext - và chính bối cảnh này xác định cách nó sẽ được thực thi. Vì vậy, để trả lời câu hỏi thứ hai của bạn, tương lai sẽ được thực thi bởi bất kỳ ExecutionContext nào nằm trong phạm vi tiềm ẩn (và dĩ nhiên nếu điều này là mơ hồ, đó là lỗi biên dịch).

Trong nhiều trường hợp, đây sẽ là số từ import ExecutionContext.Implicits.global, có thể được tinh chỉnh bởi thuộc tính hệ thống nhưng theo mặc định sử dụng ThreadPoolExecutor với một luồng cho mỗi lõi bộ xử lý.

Tuy nhiên, lịch trình là một vấn đề khác. Đối với một số trường hợp sử dụng, bạn có thể cung cấp ExecutionContext của riêng bạn luôn áp dụng cùng một độ trễ trước khi thực thi. Nhưng nếu bạn muốn sự chậm trễ được kiểm soát từ trang web cuộc gọi, thì tất nhiên bạn không thể sử dụng Future.apply vì không có tham số để truyền đạt cách thức này nên được lên lịch. Tôi sẽ đề nghị gửi các tác vụ trực tiếp đến một người thực hiện theo lịch trình trong trường hợp này.

+0

Yhanks Andrzej - hữu ích như mọi khi :) – Bober02

3

Câu trả lời của Andrzej đã đề cập đến hầu hết mọi thứ trong câu hỏi của bạn. Đáng nói đến là bối cảnh thực thi ngầm định "mặc định" của Scala (import scala.concurrent.ExecutionContext.Implicits._) là theo nghĩa đen a java.util.concurrent.Executor và toàn bộ khái niệm ExecutionContext là một trình bao bọc rất mỏng, nhưng được liên kết chặt chẽ với khung thực thi của Java.

Để đạt được điều gì đó tương tự như tương lai đã lên lịch, như Mauricio đã chỉ ra, bạn sẽ phải sử dụng lời hứa và bất kỳ cơ chế lập lịch biểu của bên thứ ba nào.

Không có cơ chế chung cho điều này được xây dựng vào Scala 2.10 tương lai là một điều đáng tiếc, nhưng không có gì gây tử vong.

Lời hứa là xử lý cho tính toán không đồng bộ. Bạn tạo một (giả sử ExecutionContext trong phạm vi) bằng cách gọi val p = Promise[Int](). Chúng tôi vừa hứa một số nguyên.
Khách hàng có thể lấy một tương lai phụ thuộc vào lời hứa đang được thực hiện, chỉ cần gọi p.future, đó chỉ là một tương lai Scala.
Thực hiện lời hứa đơn giản chỉ là vấn đề gọi số p.successful(3), tại thời điểm đó tương lai sẽ hoàn thành.

Phát 2.x giải quyết lịch biểu bằng cách sử dụng lời hứa và đồng bộ cũ 1,4 giờ Java.
Here là liên kết chống liên kết tới nguồn.

Chúng ta hãy xem xét các nguồn ở đây:

object Promise { 
    private val timer = new java.util.Timer() 

    def timeout[A](message: => A, duration: Long, unit: TimeUnit = TimeUnit.MILLISECONDS) 
       (implicit ec: ExecutionContext): Future[A] = { 
    val p = Promise[A]() 
    timer.schedule(new java.util.TimerTask { 
     def run() { 
     p.completeWith(Future(message)(ec)) 
     } 
    }, unit.toMillis(duration)) 
    p.future 
    } 
} 

này sau đó có thể được sử dụng như sau:

val future3 = Promise.timeout(3, 10000) // will complete after 10 seconds 

thông báo này là đẹp hơn nhiều so với cách cắm một Thread.sleep(10000) vào mã của bạn, mà sẽ chặn luồng của bạn và buộc chuyển đổi ngữ cảnh.

Cũng đáng chú ý trong ví dụ này là val p = Promise... ở đầu của hàm và số p.future ở cuối. Đây là một mô hình phổ biến khi làm việc với lời hứa. Mang nó đến có nghĩa là chức năng này làm cho một số lời hứa cho khách hàng, và bắt đầu một tính toán không đồng bộ để thực hiện nó.

Hãy xem here để biết thêm thông tin về lời hứa của Scala. Lưu ý rằng họ sử dụng phương thức future chữ thường từ đối tượng gói concurrent thay vì Future.apply. Các cựu đại biểu chỉ đơn giản là đại biểu sau này. Cá nhân, tôi thích chữ thường future.