Tasks aren’t deprecated, only produce()
and consume()
functions are. Tasks in Julia implement a very powerful idea of coroutines, making it possible to run multiple subroutines concurrently (although not necessarily in parallel).
produce()
and consume()
are a way to communicate between 2 tasks. Channels are a way to communicate between any number of tasks.
For example, we can create a channel with capacity 1 so that it could keep at most 1 element.
chnl = Channel{Int}(1)
# ==> Channel{Int64}(sz_max:1,sz_curr:0)
and run a separate task to fill this channel with numbers from 1 to 10:
@async for i=1:10 put!(chnl, i) end
# ==> Task (runnable) @0x00007fe67d1aa770
Local channels like this hold data in as an array that we can inspect:
chnl.data
# ==> 1-element Array{Int64,1}:
# ==> 1
Our additional task started running, put single element to the channel and stopped (switching control flow to another task) because channel is full. Now let’s take an element from the channel:
take!(chnl)
# ==> 1
chnl.data
# ==> 1-element Array{Int64,1}:
# ==> 2
As expected, take!()
returns first element from the channel. What’s more interesting is that our additional task immediately fills the channel with the next element. And stops again.
Channels also expose iterator interface, so we can read all the data using a loop:
for x in chnl println(x) end
# ==> 2
# ==> 3
# ==> 4
# ==> 5
# ==> 6
# ==> 7
# ==> 8
# ==> 9
# ==> 10
Note that the previous code will hang on because channel is still open, so the loop expects new elements, but nobody adds them. To fix it, we can modify additional task as follows:
@async begin for i=1:10 put!(chnl, i) end; close(chnl) end
# ==> Task (runnable) @0x00007fe67c843490
for x in chnl println(x) end
# ==> 1
# ==> 2
# ==> 3
# ==> 4
# ==> 5
# ==> 6
# ==> 7
# ==> 8
# ==> 9
# ==> 10
# ==> returned control
Of course, you can specify larger capacity for channels to avoid to frequent switching between tasks.
To summarize:
- Create a channel available for both - producer and consumer tasks.
- Use
put!(chnl, x)
instead ofproduce()
andtake!(chnl)
instead ofconsume()
, or just iterate over the channel. - Call
close(chnl)
to finish.