iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 11
0
自我挑戰組

Julia語言—從入門到專案系列 第 11

[Day 11] Asynchronous programming--Task

今天的章節會先介紹Julia中的Asynchronous programming。

相信大家在其他語言多多少少有碰過這類東西,像是網頁前端、寫concurrency的時候等等都會碰到。

戲說從generator

我們先從generator開始吧!

generator可以在你每次跟他要資料的時候吐出結果,你跟他要一次就吐一次,他不像comprehension一樣一次把結果都算好吐給你。

如此一來,在計算大量資料的時候不會事先佔去大量記憶體,只在有需要的時候計算結果並回傳

function countdown(n)
    println("count down from ", n)
    while n > 0
        produce(n)
        n -= 1
    end
end

以上我寫了一個會倒數的function,在呼叫他的時候你要先給他一個數字,當你每次呼叫他的時候他會從那個數字一次一次倒數,並且把數字回傳回來。

x = Task(() -> countdown(5))
println(consume(x))

回傳

count down from 5
5
println(consume(x))  # 4
...

接下來我就不列了,大家會注意到一對函數,produce()consume(),他們就像yeildsend一樣,一個會負責把回傳的值丟出去,一個負責呼叫並且接收值。

Task

在Python裏面有個東西叫作coroutine,他是個好用的東西,他可以像function一樣被呼叫之後暫停,然後先去做別的事情,之後再回來這邊完成後面的事情。
在Asynchronous programming中是少不了他的,基本上他不會佔到額外的記憶體空間,像是如果function被呼叫的時候,電腦會配置給他額外的記憶體空間,當function的數量變多,記憶體空間也會隨之被消耗,相對,呼叫coroutine不會佔去額外的記憶體空間。

相對應coroutine的概念,Julia把他包裝成一個有狀態的物件,稱為Task。
我們來看看Task的作用吧!

function add_something(n)
    x = produce("我們開始吧!")  # 會吐出值給consume()
    while true
        x = produce(x + n)
    end
end

foo = @task add_something(100)  # 這是一個task,等同於 Task(() -> add_something(100))

我們定義一個Task,他會把我們一開始給的值n加上他後來接收到的x,然後把他回傳給我們。

println(consume(foo))  # 我們開始吧!
println(consume(foo, 5))  # 105
println(consume(foo, 7))  # 107
println(consume(foo, 9))  # 109

有了這樣的特性就容易實作多工 (multitasking),當然也可以決定task的排程跟優先權,也就成為了一個作業系統的核心

使用task與function不同的點在於:

  • 切換task並不使用任何空間,因為CPU不會意識到task的存在,也不會做context switch
  • 在task間切換可以是任意順序,你想暫停目前的task轉到其他task都是可以的喔

上一篇
[Day 10] Julia是個什麼樣的語言
下一篇
[Day 13] 前哨站--functional patterns
系列文
Julia語言—從入門到專案31

尚未有邦友留言

立即登入留言