0

AFAIK TChan 充当枢纽,发送的每条消息都会被其他人看到,对吧?!
我想要一个 TChan 作为开关来向特定线程发送消息,并且还支持广播。
有这样的事吗?

4

1 回答 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从子线程而不是主线程调用,一些writeTChans 可能首先发生,这意味着子线程可能看不到所有项目。

  • 由于没有人在读取master通道,写入它的项目会堆积起来,可能不会被垃圾收集。为避免此警告,请使用newBroadcastTChan创建master频道。

于 2012-10-21T02:02:49.650 回答