Java多线程:线程不会完成run()方法
我试图理解java多线程,但在让这个线程完成其run方法时遇到了一些问题 我有两个工作线程使用阻塞队列中的消息。他们应该对传递的值做一些简单的操作,并将结果附加到文件中。因为我不想为每个I/O操作打开一个文件读取器,所以我想使用StringBuilder逐步构建报告,并在线程被踢出主循环时编写报告。然而,循环后的代码似乎从未运行过 以下是线程中运行的代码:Java多线程:线程不会完成run()方法,java,multithreading,Java,Multithreading,我试图理解java多线程,但在让这个线程完成其run方法时遇到了一些问题 我有两个工作线程使用阻塞队列中的消息。他们应该对传递的值做一些简单的操作,并将结果附加到文件中。因为我不想为每个I/O操作打开一个文件读取器,所以我想使用StringBuilder逐步构建报告,并在线程被踢出主循环时编写报告。然而,循环后的代码似乎从未运行过 以下是线程中运行的代码: @Override public void run() { StringBuilder builder = new StringB
@Override
public void run() {
StringBuilder builder = new StringBuilder();
while(true) {
if(!shouldRun) break;
try {
WorkMessage msg = (WorkMessage) ((BlockingQueue) inputQueue).take();
int payload = msg.payload;
LocalTime time = msg.timeCreated;
String report = "Adder got message at: " + time + ". Result: " + (payload + toAdd);
builder.append(report);
} catch (InterruptedException ie) {
System.out.println("ERROR IN ADDER: " + ie.getMessage());
}
}
writeToReportFile(builder.toString());
}
writeToReportFile
方法是未调用的方法。当我在控制线程中将shouldlrun
设置为false时,它似乎会在while循环结束后跳过代码。我没有直接从外部线程将shouldlrun
设置为false,而是从外部调用一个内部kill()
方法,该方法在内部将shouldlrun
设置为false
有人知道为什么会这样吗?我确信我只是缺少了一些简单的东西。你应该使用线程中断来终止你的线程,你的手动滚动标志方法给你带来了问题,因为更新到shouldRun标志不可见,队列无法停止阻塞
如果您的控制线程调用Worker对象上的kill方法,那么您的shouldRun标志将由该线程设置。需要使用volatile使其可见,以便工作线程(正在执行run方法)可以看到它
如果不使用volatile(或者使用AtomicBoolean或其他方法使此更改在线程之间可见),JVM可以自由地将处理器本地缓存中的变量内容保持为其他线程不可见,或者优化工作线程正在运行的代码中的签出
使用并发类(如队列)的线程需要使用中断,而不是依赖于手动滚动的标志,以便它们包含的组件(如队列)上的操作可以响应取消请求。否则,您的队列无法知道您的手动滚动标志,因此它无法停止阻塞以响应对kill方法的调用。线程很可能由于take()而被阻塞。为什么不使用poll(time,timeunit)方法测试这段代码呢?poll(time,timeunit)方法将等待指定的时间,然后返回,因此在等待指定的时间后,它将检查您的标志shouldlrun,并将退出循环 资料来源: 另外,请声明变量应作为volatile运行。 原因:以下摘录摘自《实践中的Java并发》一书: 服务器JVM比客户端JVM执行更多的优化,例如从循环中提升未在循环中修改的变量
所以,在使用服务器JVM的环境中,您可能会在无限循环中结束,因为shouldRun变量不会在循环中修改。shouldRun是否为volatile?不,但我认为我不需要将其设置为volatile,因为我没有直接从控制线程设置它。我正在使用该线程类中的一个方法(由控制线程调用以执行终止)来更改它您使用的代码>方法是一个阻塞操作,因此即使更改标志,如果(!shouldRun)中断,代码也永远不会到达
代码>如果从未收到工作消息
。对于您发布的代码段,唯一的方法是从类中更改shouldRun标志,导致中断异常
,关闭通道等,并杀死它所在的作业。谢谢