Là cấu trúc mà khi biên dịch các module được biên dịch một cách riêng biệt.

Future là một khái niệm trừu tượng mô tả về kết quả của một xử lý không đồng bộ. Nó có nghĩa là nếu bạn đưa các xử lý tính toán vào Future thì nó sẽ được thực thi trong một thread mới riêng biệt, tức là thread chính của chương trình có thể thực hiện các tác vụ khác mà không cần phải chờ đợi.

Trong bài viết này, chúng ta sẽ viết một thư viện Future với Ruby và cùng với đó, các bạn có thể tìm hiểu thêm về các thư viện concurrency mà Ruby cung cấp.

Future hữu ích như thế nào?

Trước khi bắt đầu vào implement, hãy xem Future hữu ích như thế nào. Future rất thích hợp để gửi các HTTP request song song. Chúng ta sẽ bắt đầu bằng một ứng dụng ruby đơn giản là lấy một chuyện đùa bất kỳ về Chuck Norris từ The Internet Chuck Norris Database

require "open-uri" require "json" require "benchmark" class Chucky URL = "//api.icndb.com/jokes/random" def sequential open[URL] do |f| f.each_line { |line| puts JSON.parse[line]["value"]["joke"] } end end end Chucky.new.sequential

Mỗi lần hàm sequential được gọi, chương trình sẽ lấy một chuyện đùa bất kỳ về Chuck Norris. Vấn đề gì sẽ xảy ra nếu ta muốn lấy nhiều hơn 10 chuyện? Giải pháp thông thường sẽ là:

10.times { chucky.sequential }

Không may là viết thế này sẽ làm lãng phí tài nguyên của CPU và thời gian của chúng ta. Mỗi lần request được gửi để lấy dữ liệu, luồng xử lý chính sẽ bị block và phải chờ request được xử lý xong trước khi chuyển đến request tiếp theo. Với Future, ta hoàn toàn có thể khắc phục được điều đó.

Viết test

Chúng ta sẽ viết một gem Future riêng biệt với TDD [Test Driven Development]. Đầu tiên, ta sẽ tạo một Ruby gem mới với câu lệnh:

bundle gem futurama

Tiếp theo, chạy bin/setup để thiết lập các dependencies

Bước 1

Test đầu tiên của chúng ta sẽ rất đơn giản:

require "spec_helper" require "timeout" module Futurama describe "Future" do it "returns a value" do future = Futurama::Future.new { 1 + 2 } expect[future].to eq[3] end end end

Test trên mô tả cách thức để tạo ra một Future. Một Future object sẽ nhận một block chứa các tác vụ và khi object Future được gọi đến, nó sẽ trả về giá trị của các tác vụ được truyền vào từ block.

Sau khi đã có test, ta sẽ bắt đầu viết code cho nó. Tạo một file tên là future.rb trong folder lib/futurama. Sau đó là đưa require.rb vào lib/futurama.rb như sau:

require "futurama/version" require "futurama/future" module Futurama end

Để có thể pass được test, một Future object cần phải:

  • nhận một block

  • trả về giá trị trong block khi nó được gọi

Với điều kiện đầu tiên, khá đơn giản:

module Futurama class Future def initialize &block @block = block end end end

Với điệu kiện thứ 2 sẽ phức tạp hơn một chút:

require "delegate" module Futurama class Future

Chủ Đề