AFAIK TChan充当集线器,发送的每条消息都被别人看到了吗?!
我想要一个TChan作为交换机向特定线程发送消息,并且还支持广播
有这样的事吗?
答案 0 :(得分:3)
编辑:我重新阅读了你的问题。这个答案并没有完全解决“选择性发送”,尽管它澄清了TChan
可以做什么。
下面描述的“广播”方法将唤醒所有听众(虽然从好的方面来看,每个项目不会制作1000份副本)。为避免这种情况,请使用Map
方法作为@Mikhail建议。我是在chat server example中完成的。
TChan
是一个FIFO队列:
writeTChan
在最后添加一个项目。
readTChan
从头开始读取项目。
例如,以下示例分叉10个线程,这些线程在单个通道上进行战斗:
import Control.Concurrent
import Control.Concurrent.STM
import Control.Monad
main = do
chan <- newTChanIO
forM_ [1..10] $ \i ->
forkIO $
forever $ do
x <- atomically $ readTChan chan
putStrLn $ "Thread " ++ show i ++ ": " ++ show x
mapM_ (atomically . writeTChan chan) [1..1000]
-- Wait for channel to empty out
atomically $ do
empty <- isEmptyTChan chan
when (not empty) retry
这里,每个项目只由一个线程读取。
相比之下,以下示例通过使用dupTChan制作十个频道副本,将一个项目流“广播”到10个主题:
import Control.Concurrent
import Control.Concurrent.STM
import Control.Monad
main = do
master <- newTChanIO
forM_ [1..10] $ \i -> do
chan <- atomically $ dupTChan master
forkIO $
forever $ do
x <- atomically $ readTChan chan
putStrLn $ "Thread " ++ show i ++ ": " ++ show x
mapM_ (atomically . writeTChan master) [1..100]
-- Give threads time to complete
threadDelay 1000000
现在每个线程都会获取写入频道的所有项目。
需要注意的几个细微之处:
写入dupTChan
之前的频道的项目不会出现在新频道中。如果我们从子线程而不是主线程调用dupTChan
,则可能首先发生一些writeTChan
,这意味着孩子们可能看不到所有项目。
由于没有人正在阅读master
频道,因此写入该频道的内容会堆积起来,很可能不会被垃圾收集。要避免这种警告,请使用newBroadcastTChan创建master
频道。