在两个线程之间进行通信

25
我有一个线程A,它有一个列表。列表中保存了一些对象。现在我想设计一个机制,通过这个机制我可以向线程A发送一些消息。
线程A在一个循环中运行(它不等待或休眠)。 另一个线程B向线程A发送一些消息,线程A会清空它的所有队列。
我如何在线程之间发送消息?
class A extends Thread {
    List<Object> objs = something; //Init it
    void run() {
        while(true) {
            //Body which works on objects.
            //After receiving an external message, "A" should perform some action, for example, empty objects.
        }
    }
}

编辑: 我可以这样做吗?
class A extends Thread {
    List<Object> objs = something; //Init it
    Boolean flag = false;

    public void setFlag(boolean value) {
        synchronized(flag) {
            this.flag = value;
        }
    }

    public void getFlag() {
        synchronized(flag) {
            return this.flag;
        }
    }

    void run() {
        while(true) {
            //Body which works on objects.
            //After receiving an external message, A should perform some action, for example, empty objects.
            if (getFlag == true)
                //Empty list
        }
    }
}

4
在Java中,通常不直接在线程之间传递消息,而是使用同步对象在线程之间传递值。 - toto2
我在我的新编辑中将实例变量作为方法同步,这样会有效吗? - akshay
1
@akshay,你的编辑看起来不错(除了你应该写成 if (getFlag() == true))。 - toto2
或者更好的是 if (getFlag())。使用 flag == trueflag == false 来测试布尔值是不好的风格,而且会导致 if (flag = true) 错误的发生。 - undefined
3个回答

44
你可以用一个消息对象的BlockingQueue。其他线程会将消息放入队列中。在while(true)循环的一部分,线程Apoll队列并处理到达的任何消息。
代码示例:
class A extends Thread{
 List<Object>  objs = something ;//init it
 BlockingQueue<Message> queue = new LinkedBlockingQueue<Message>();
 void run(){
     while(true){
       Message msg;
       while ((msg = queue.poll()) != null) {
         // process msg
       }
       // do other stuff
     }
   }
}

其他线程现在可以调用 queue.put() 方法向线程 A 发送消息。


队列是线程A的实例变量。如果在线程A检索它时,线程B会向其中添加一些值,那么这不会成为一个问题吗? - akshay
1
@akshay: (1) queue 不必是 A 的成员(我将其仅作为示例简化了);(2) BlockingQueue 是线程安全的,因此无论如何都不会有问题。 - NPE
@NPE queue变量应该标记为volatile吗?因为它会从其他线程更新。 - abalcerek
@abalcerek 我认为 queue 应该是 final,但绝对不是 volatile。队列本身并没有被经常替换,也不是经常更改的原始值。它始终是指向同一对象的引用,因此每次需要时都无需从主内存加载该引用。 - Theodore Murdock
你能解释一下为什么这个队列需要是阻塞的吗? - Ring
显示剩余2条评论

1
在简单的情况下,您可以向线程A类添加一些实例变量,并让线程B设置其值以指示线程A必须清除其队列。在更高级的情况下,您可以使用一些消息队列,线程A和B都可以访问。 B会将消息放在那里,而A会读取并采取行动。
在所有情况下,对变量或队列的访问必须得到适当的保护,以供多个线程访问。

1
你应该能够为类"A"添加一个方法,该方法可以在代码中的其他地方被调用。只需将类"A"实例的引用保存在一个可访问的位置即可。
class A extends Thread{
 List<Object>  objs = something ;//init it
 void run(){
   while(true){
       //body which works on objs
       //open receiving external message A should perform some action ie empty objs
     }
   }
  void ChangeState()
  {
     //clear objs
  } 
}

会引起问题。由于我的 for 循环大量使用 objs,如果突然清除它,将会引起问题。 - akshay
2
你的问题涉及如何向线程A发送消息以便它执行所需的操作。我的回答直接针对这个问题。我没有涉及线程安全,因为我假设在清除或读取任何内容之前,你会在代码中进行适当的检查(同步)。 - Garvin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接