AFAIK TChan 充当枢纽,发送的每条消息都会被其他人看到,对吧?!
我想要一个 TChan 作为开关来向特定线程发送消息,并且还支持广播。
有这样的事吗?
问问题
531 次
1 回答
3
编辑:我重新阅读了你的问题。这个答案并没有完全解决“选择性发送”,尽管它澄清了 aTChan
可以做什么。
下面描述的“广播”方法将唤醒所有听众(虽然从好的方面来说,它不会为每个项目制作 1000 个副本)。为避免这种情况,请使用Map
@Mikhail 建议的方法。我在我的聊天服务器示例中这样做了。
ATChan
是一个先进先出队列:
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 个副本,将项目流“广播”到 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
s 可能首先发生,这意味着子线程可能看不到所有项目。由于没有人在读取
master
通道,写入它的项目会堆积起来,可能不会被垃圾收集。为避免此警告,请使用newBroadcastTChan创建master
频道。
于 2012-10-21T02:02:49.650 回答