两个线程如何在两个线程运行时进行通信?

时间:2012-10-01 16:27:59

标签: java multithreading concurrency

我一直试图教自己并发,而且我遇到了一个问题。我知道两个Java线程可以通过wait()notify()相互通信。但是,这需要一个线程处于非活动状态,而且基本上只需要坐在一起即可。直到另一个人醒来。

是否可以让两个线程同时运行并让它们监听另一个线程的通知?这是通过并发技术还是像ActionListener

那样实现的

例如,我正在测试它的项目基本上是一个网格,其中不同的实体在不同的单元格中四处游荡。当两个实体碰巧徘徊在同一个单元格中时,我希望一个人通知另一个实体,并根据这一点发生不同的事情(例如,问候语:"你好!" )。但就目前而言,使用wait / notify范例,其中一个线程/实体必须简单地坐在一个单元格中等待另一个进入;他们无法四处走动。

5 个答案:

答案 0 :(得分:4)

有几种方法可以在线程之间进行通信。使用最常用的方法,您可以使用实例变量在线程之间共享信息,但您必须注意只从一个线程写入或同步任何更新到共享变量。或者,您可以使用专为线程间通信设计的Piped I / O流,或在线程之间传递原始数据。一个线程将信息写入流,而另一个线程将其读取。

这是一个示例方法,它将读取慢速网络连接的输出并使用线程将其转储到System.out。

    public void threads() throws IOException {
    final PipedOutputStream outputForMainThread = new PipedOutputStream();
    new Thread(new Runnable() {
        @Override
        public void run() {
            while(moreDataOnNetwork()) {
                byte[] data = readDataFromNetwork();
                try {
                    outputForMainThread.write(data);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }).start();
    BufferedReader reader = new BufferedReader(new InputStreamReader(new PipedInputStream(outputForMainThread)));
    for(String eachLine = reader.readLine(); eachLine != null; eachLine = reader.readLine()) {
        System.out.println(eachLine);
    }
}

然而,几乎听起来你想要一个事件回调机制,当另一个线程检测到某个条件时,会通知一个线程(你的用户界面线程)。根据您的平台,大部分内容都已经完成。例如,使用Android,您可以拥有一个确定网格实体移动的线程。它会向主用户界面线程发送更新以重新绘制屏幕。这样的更新可能类似于:

public void gridEntityDidUpdate(final Point fromLocation, final Point toLocation) {
    Activity activity = getMainActivity();
    activity.runOnUiThread(
            new Runnable() {
                @Override
                public void run() {
                    updateScreen(fromLocation, toLocation);
                    if(pointsAreCoincedent(fromLocation, toLocation)) {
                        System.out.println("Hello there!");
                    }
                }
            }
    );
}

private void updateScreen(Point fromLocation, Point toLocation) {
    //Update the main activity screen here
}

在这种情况下,您有一个后台线程可以解决所有屏幕元素的位置,并在元素位置发生变化时通知主线程。有一种提取方法可以确定2个点是巧合的还是相同的。

答案 1 :(得分:1)

您可以使用Erlang 语言安全地与在Processes之间进行通信,该Java在自己的地址空间内运行{{1}}作为一个更好,更安全的线程替代品。

答案 2 :(得分:1)

  

我一直在努力教自己并发,我遇到了一个问题。据我所知,两个Java线程可以通过wait()和notify()进行相互通信。

“经典”Java线程教程早期教授wait / notify。回到Java 1.1,1.2时间框架,这就是全部。

但是,如果您可以获得Brian Goetz的优秀“Java Concurrency in Practice”的副本,则在第IV节高级主题的第14章“构建自定义同步器”之前不会讨论等待/通知。我在这里严厉地解释,但我得到的印象是“好的,如果你已经阅读了300个以前的页面,到目前为止讨论的构建块都没有满足你的需求,那么你可以尝试使用wait / notify构建你自己的”。 / p>

我的观点是,wait / notify虽然非常重要,但可能不是开始学习并发的最佳位置。这个问题中的一些答案/评论(生产者/消费者,ExecutorService)指的是在Java 5中添加的更高级别的并发构建块。尽管这些东西是后来添加的,但这是你应该首先学习的东西。 / p>

回到你的问题 - 这里有几点想法:

如果这是一个GUI应用程序,并且您希望让后台线程做一些工作,请查看SwingWorker。我已成功使用SwingWorker(第9.3.3节),其中后台线程从阻塞队列中读取消息(第5.3节)确实有效,并通过调用更高级别的“发布”方法通知GUI线程。没有“等待/通知” - 至少在我的代码中没有。

如果应用程序不是基于Swing的,并且您希望让不同的线程并行执行任务并偶尔向对方发送消息,请考虑ZeroMQ“充当并发框架的套接字库”。使用ZeroMQ,每个线程都运行一个事件循环,用于读取和处理消息。线程可以通过向自己发送消息来调度其自己的线程上的工作。它可以通过向该线程(套接字)发送消息来安排工作/通知不同的线程。

无论如何,祝你好运。

答案 3 :(得分:0)

尝试使用ThreadManager类,它有List<Thread>,有点像信号量对象。你的线程应该能够从那里找到并引用其他线程。

答案 4 :(得分:0)

  

是否可以让两个线程同时运行并让它们监听另一个线程的通知?

每当他们不等待时,他们可以同时做某事。如果他们似乎只是在等待彼此,那么你可能会更好地使用一个线程。 (使用多线程并不总是更好)

  

这是通过并发技术完成的,还是像ActionListener那样实现的?

如何解决问题更可能是一个设计问题。当线程之间的交互最少时,线程最有效。如果他们高度依赖彼此,你应该考虑使用更少的线程。

  

但是就目前而言,使用wait / notify范例,其中一个线程/实体必须简单地坐在一个单元格中等待另一个进入;

我不明白为什么你需要等待/通知这里。我只是让他们四处走动,当他们在同一个小区时,互相发送消息。