我一直试图教自己并发,而且我遇到了一个问题。我知道两个Java线程可以通过wait()
和notify()
相互通信。但是,这需要一个线程处于非活动状态,而且基本上只需要坐在一起即可。直到另一个人醒来。
是否可以让两个线程同时运行并让它们监听另一个线程的通知?这是通过并发技术还是像ActionListener
?
例如,我正在测试它的项目基本上是一个网格,其中不同的实体在不同的单元格中四处游荡。当两个实体碰巧徘徊在同一个单元格中时,我希望一个人通知另一个实体,并根据这一点发生不同的事情(例如,问候语:"你好!" )。但就目前而言,使用wait / notify范例,其中一个线程/实体必须简单地坐在一个单元格中等待另一个进入;他们无法四处走动。
答案 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范例,其中一个线程/实体必须简单地坐在一个单元格中等待另一个进入;
我不明白为什么你需要等待/通知这里。我只是让他们四处走动,当他们在同一个小区时,互相发送消息。