java - 如何正确使用条件队列
问题描述
我有一个包含“任务”对象列表的 taskList 对象“持有者”。在一个循环中,我从文本文件中读取命令,并在每一行上添加带有命令的新任务对象并将其添加到“持有人”对象中。命令的格式为“cat source_file1 source_file2 output_file”,如果其中一个文件丢失,我希望线程等待,然后继续执行新命令。我正在尝试使用具有以下谓词的条件队列(如果命令的两个文件都存在,则唤醒并完成工作)直到睡眠。当第一个线程进入等待状态时,我正在使用两个线程进行测试,程序永远挂起,并且它没有让其他线程有机会生成等待线程丢失的文件。
public class MyTaskManager {
public static void main(String[] args) {
List<Thread> threads = new ArrayList<>();
TaskHolder holder = new TaskHolder();
for (int i = 0; i < 1; i++) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(
new FileInputStream("commands.txt")));
String line = "";
while ( ( line = br.readLine() ) != null) {
String[] in = line.split(" ");
File dep0 = new File(in[1]), dep1 = new File(in[2]);
holder.addTask(new Task(dep0, dep1));
synchronized (holder) {
System.out.println(Thread.currentThread().getName());
while (!dep0.exists() || !dep1.exists()) {
holder.wait();
}
}
Process process = Runtime.getRuntime()
.exec(new String[]{"bash", "-c", in[0] + " " + in[1] + " " + in[2]});
process.getInputStream().transferTo(new FileOutputStream(in[3]));
holder.notifyAll();
}
} catch (IOException | InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
}
});
threads.add(t);
}
for (int i = 0; i < 1; i++)
threads.get(i).start();
for (int i = 0; i < 1; i++) {
try {
threads.get(i).join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class TaskHolder {
private List<Task> taskList;
TaskHolder() {
taskList = new ArrayList<>();
}
void addTask(Task task) {
taskList.add(task);
}
List<Task> getTaskList() {
return taskList;
}
}
解决方案
您没有调用notify
. 此外,holder
您正在同步的内容实际上并不能保护任何东西。您必须使用锁来保护您正在等待更改的共享状态。
听起来您不了解条件的意义,也不了解它们的工作原理。简单地说,它们提供了一个原子的“解锁并等待”操作来解决以下问题:
- 要检查某些共享状态,我们必须持有一个锁。
- 要等待共享状态改变,我们必须释放锁,以便另一个线程可以改变共享状态。
这将允许没有原子“解锁和等待”操作的死锁。这就是wait
目的 - 如果您解锁然后等待,它是一个原子的“解锁并等待”以避免竞争条件。如果这不是您遇到的问题,那么wait
就不是您需要的解决方案!
这不是你遇到的问题。所以这些不是你要找的机器人。不要使用synchronized
- 它用于线程之间的通信。并且不要使用wait
,它用于当您需要原子“解锁并等待”操作以避免竞争条件时。
推荐阅读
- php - 上传的图片坏了。Laravel 日志显示 production.ERROR: Call to undefined function Illuminate Illuminate\Filesystem\finfo_file()
- c++ - Ofstream 似乎没有输出
- rxjs - 为什么 subject.onNext(3) 在这里打印?
- javascript - 动态添加/删除表单组并为每个输入提供唯一的 ID 和名称
- node.js - 在服务器中部署时将 API 请求路由到 MEAN 应用程序中的节点服务器
- vba - 如果数据源没有记录,则跳过 MS Word 邮件合并
- perl - 我应该使用哪种 OAuth2 授权类型?
- c# - 使控制台窗口脱离“选择模式”以防止崩溃
- html - 为什么我的浮动容器在我的 div 下而不是从新行开始
- javascript - 如何修复 Ajax 从数据库中获取任何内容?