수색…
기본 채널 작업 : 생성, 퍼팅, 종료, 닫기 및 버퍼.
core.async
는 값을 가져 와서 채널 에 값을 넣는 프로세스 를 만드는 것에 관한 것입니다.
(require [clojure.core.async :as a])
chan
채널 만들기
chan
함수를 사용하여 채널을 만듭니다.
(def chan-0 (a/chan)) ;; unbuffered channel: acts as a rendez-vous point.
(def chan-1 (a/chan 3)) ;; channel with a buffer of size 3.
(def chan-2 (a/chan (a/dropping-buffer 3)) ;; channel with a *dropping* buffer of size 3
(def chan-3 (a/chan (a/sliding-buffer 3)) ;; channel with a *sliding* buffer of size 3
>!!
로 채널에 값 넣기 >!!
및 >!
>!!
값을 사용하여 값을 채널에 넣을 수 있습니다 >!!
:
(a/>!! my-channel :an-item)
nil
제외한 모든 값 (문자열, 숫자,지도, 컬렉션, 객체, 다른 채널 등)을 채널에 넣을 수 있습니다.
;; WON'T WORK
(a/>!! my-channel nil)
=> IllegalArgumentException Can't put nil on channel
채널의 버퍼에 따라 >!!
현재 스레드를 차단할 수 있습니다.
(let [ch (a/chan)] ;; unbuffered channel
(a/>!! ch :item)
;; the above call blocks, until another process
;; takes the item from the channel.
)
(let [ch (a/chan 3)] ;; channel with 3-size buffer
(a/>!! ch :item-1) ;; => true
(a/>!! ch :item-2) ;; => true
(a/>!! ch :item-3) ;; => true
(a/>!! ch :item-4)
;; now the buffer is full; blocks until :item-1 is taken from ch.
)
안쪽에서 (go ...)
블록을 사용 a/>!
사용할 수 있습니다 a/>!
a/>!!
대신에 a/>!!
:
(a/go (a/>! ch :item))
논리적 동작은 a/>!!
와 같습니다 a/>!!
, 실제 OS 스레드 대신에 goroutine의 논리적 프로세스 만 차단할 것입니다.
a/>!!
내부 (go ...)
블록은 anti-pattern입니다.
;; NEVER DO THIS
(a/go
(a/>!! ch :item))
<!!
하여 채널에서 가치를 얻습니다 <!!
<!!
사용하여 채널에서 가치를 <!!
:
;; creating a channel
(def ch (a/chan 3))
;; putting some items in it
(do
(a/>!! ch :item-1)
(a/>!! ch :item-2)
(a/>!! ch :item-3))
;; taking a value
(a/<!! ch) ;; => :item-1
(a/<!! ch) ;; => :item-2
채널에서 사용할 수있는 항목이 없으면 a/<!!
값이 채널에 저장 될 때까지 (또는 채널이 닫힐 때까지), 현재 스레드를 차단합니다.
(def ch (a/chan))
(a/<!! ch) ;; blocks until another process puts something into ch or closes it
안쪽에서 (go ...)
블록을 사용 a/<!
a/<!!
대신 a/<!!
:
(a/go (let [x (a/<! ch)] ...))
논리적 동작은 a/<!!
와 같습니다 a/<!!
, 실제 OS 스레드 대신에 goroutine의 논리적 프로세스 만 차단할 것입니다.
a/<!!
사용 a/<!!
내부 (go ...)
블록은 anti-pattern입니다.
;; NEVER DO THIS
(a/go
(a/<!! ch))
채널 닫기
a/close!
close를 사용 하여 채널을 a/close!
:
(a/close! ch)
채널이 닫히고 채널의 모든 데이터가 모두 소모되면 테이크는 항상 nil
반환합니다.
(def ch (a/chan 5))
;; putting 2 values in the channel, then closing it
(a/>!! ch :item-1)
(a/>!! ch :item-2)
(a/close! ch)
;; taking from ch will return the items that were put in it, then nil
(a/<!! ch) ;; => :item-1
(a/<!! ch) ;; => :item-2
(a/<!! ch) ;; => nil
(a/<!! ch) ;; => nil
(a/<!! ch) ;; => nil
;; once the channel is closed, >!! will have no effect on the channel:
(a/>!! ch :item-3)
=> false ;; false means the put did not succeed
(a/<!! ch) ;; => nil
비동기 put!
a/>!!
대한 대안으로 a/>!!
(차단할 수 있음), a/put!
부를 수 있습니다 a/put!
선택적 콜백을 사용하여 다른 스레드의 채널에 값을 넣을 수 있습니다.
(a/put! ch :item)
(a/put! ch :item (fn once-put [closed?] ...)) ;; callback function, will receive
ClojureScript에서는 현재 스레드를 차단할 수 없으므로 a/>!!
지원되지 않는다 put!
(go)
블록 외부에서 채널에 데이터를 입력하는 유일한 방법입니다.
비동기가 걸립니다 take!
a/<!!
(현재 스레드를 차단할 수 있음), a/take!
사용할 수 a/take!
비동기 적으로 채널에서 값을 가져 와서 콜백으로 전달합니다.
(a/take! ch (fn [x] (do something with x)))
드롭 및 슬라이딩 버퍼 사용
드롭 및 슬라이딩 버퍼를 사용하면 put은 결코 차단되지 않지만 버퍼가 가득 차면 데이터가 손실됩니다. 슬라이딩 버퍼가 추가 된 첫 번째 데이터를 잃어 버리는 반면 버퍼를 삭제하면 마지막 데이터가 손실됩니다.
드롭 버퍼 예제 :
(def ch (a/chan (a/dropping-buffer 2)))
;; putting more items than buffer size
(a/>!! ch :item-1)
=> true ;; put succeeded
(a/>!! ch :item-2)
=> true
(a/>!! ch :item-3)
=> false ;; put failed
;; no we take from the channel
(a/<!! ch)
=> :item-1
(a/<!! ch)
=> :item-2
(a/<!! ch)
;; blocks! :item-3 is lost
슬라이딩 버퍼 예제 :
(def ch (a/chan (a/sliding-buffer 2)))
;; putting more items than buffer size
(a/>!! ch :item-1)
=> true
(a/>!! ch :item-2)
=> true
(a/>!! ch :item-3)
=> true
;; no when we take from the channel:
(a/<!! ch)
=> :item-2
(a/<!! ch)
=> :item-3
;; :item-1 was lost