[英]How to properly use notify and wait
How to use notify and wait properly.如何正确使用通知和等待。 I have just two threads to test my logic.
我只有两个线程来测试我的逻辑。 Is it as follows i create one thread which will execute a command of the type get
file_1 file_2
and create file3
with the type
cmd.是不是如下我创建一个线程,它将执行类型为 get
file_1 file_2
的命令并创建type
cmd 的file3
。 My first task don't have file_2
so it will be put in wait state on a condition predicate that checks if the both files are present with .exists() method on the file.我的第一个任务没有
file_2
因此它将在条件谓词上处于等待状态,该条件谓词检查两个文件是否都存在文件上的 .exists() 方法。 The second thread will create file_2
and it will notify the first thread then the other thread will wake up and execute his job.第二个线程将创建
file_2
并通知第一个线程然后另一个线程将唤醒并执行他的工作。 The problem is that after the thread that is waiting wakes up it doesn't have his job but the other's thread job.问题是在等待的线程唤醒后,它没有他的工作,而是另一个线程的工作。 For example if
Thread-1
have to execute file1 file2 > file3
and it is in a wait state.例如,如果
Thread-1
必须执行file1 file2 > file3
并且它处于等待状态。 And Thread-2
have to execute file3 file4 > file2
so it creates the file2
and notify Thread-1
.并且
Thread-2
必须执行file3 file4 > file2
所以它创建file2
并通知Thread-1
。 After Thread-1 woke up it have file3 fil4 > file2
and not his files.线程 1 醒来后,它有
file3 fil4 > file2
而不是他的文件。 I am dumping everything to the console and when the two threads are taking the tasks from the commands file they take the proper one's they don't have the same task but after Thread-1
woke up it have the Thread-2
task.我正在将所有内容转储到控制台,当两个线程从命令文件中获取任务时,它们会获取正确的任务,但它们没有相同的任务,但是在
Thread-1
唤醒后,它具有Thread-2
任务。 Can someone help me to understand how to use wait and notify for this case and in any other of course.有人可以帮助我了解如何在这种情况下以及在任何其他情况下使用等待和通知。 I have read Java Concurrency in practice but they have only put and take methods there with wait and notify also the examples in google are naive and they work as expected.
我已经在实践中阅读了 Java Concurrency,但他们只在那里放置和使用方法并等待并通知 google 中的示例是幼稚的,它们按预期工作。 Thanks in advance.
提前致谢。
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class MyTaskManager {
private static AtomicInteger id = new AtomicInteger();
private static String[] in;
private static String cmd;
private static Task task;
private static Process process;
private static MyTaskManager taskManager;
public static void main(String[] args) {
taskManager = new MyTaskManager();
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
// Assign work
synchronized (taskManager) {
String line = Files.readAllLines(Paths.get("commands.txt"))
.get(id.get());
id.getAndIncrement();
in = line.split(" ");
cmd = in[0] + " " + in[1] + " " + in[2] + " " + in[3] + " " + in[4];
task = new Task(cmd);
System.out.println(cmd);
}
// After the thread is woked up it checks the condition again
// but this time it is taken the other thread object
synchronized (taskManager) {
while (!task.checkCondition(task)) {
System.out.println("Waiting thread " + Thread.currentThread().getName());
System.out.println("Write file in wait " + task.getOutput_file());
System.out.println("---------------------------------");
taskManager.wait();
System.out.println(Thread.currentThread().getName() + " after sleep");
}
}
process = Runtime.getRuntime()
.exec("cmd /c start cmd.exe /k \"" + task.getCmd() + "\"");
process.waitFor();
synchronized (taskManager) {
taskManager.notifyAll();
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
// Assign work
synchronized (taskManager) {
String line = Files.readAllLines(Paths.get("commands.txt"))
.get(id.get());
id.getAndIncrement();
in = line.split(" ");
cmd = in[0] + " " + in[1] + " " + in[2] + " " + in[3] + " " + in[4];
task = new Task(cmd);
System.out.println(cmd);
}
process = Runtime.getRuntime()
.exec("cmd /c start cmd.exe /k \"" + task.getCmd() + "\"");
process.waitFor();
synchronized (taskManager) {
taskManager.notifyAll();
System.out.println("Notifying " + Thread.currentThread().getName());
}
} catch (IOException | InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
}
});
BlockingQueue<Runnable> worksQueue = new
ArrayBlockingQueue<>(10);
RejectedExecutionHandler rejectionHandler = new
RejectedExecutionHandlerImpl();
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 2, 20,
TimeUnit.SECONDS, worksQueue, rejectionHandler);
executor.prestartAllCoreThreads();
List<Runnable> taskGroup = new ArrayList<>();
taskGroup.add(t);
taskGroup.add(t1);
worksQueue.add(new MultiRunnable(taskGroup));
executor.shutdown();
}
}
boolean checkCondition(Task task) {
String[] in = task.cmd.split(" ");
File dep1 = new File(in[1]);
File dep2 = new File(in[2]);
return dep1.exists() && dep2.exists();
}
The problem with mutual wait-notify calls in your case is the fact that that one thread can finish its job and invoke notify
before another thread invokes wait
.在您的情况下,相互 wait-notify 调用的问题在于,一个线程可以完成其工作并在另一个线程调用
wait
之前调用notify
。 Notification is not "remembered" so if notify is called before actual wait
is, then waiting thread will wait forever (well, until another notify).通知不会“记住”,因此如果在实际
wait
之前调用通知,则等待线程将永远等待(好吧,直到另一个通知)。
If I am not mistaken, you want T1 has to do some job, wait for some notification from T2 and then do some other + exit.如果我没记错的话,你想让 T1 做一些工作,等待 T2 的一些通知,然后做一些其他的 + 退出。 If this is correct, it will be much simpler for you to use
CountDownLatch
or Semaphore
如果这是正确的,那么使用
CountDownLatch
或Semaphore
会简单得多
Both can cancel effect of racing conditions mentioned above.两者都可以取消上述赛车条件的影响。 Countdown latch can be "counted down" when other threads are waiting for it to do so, or prior that which will result in "waiting thread" to never have to wait as "the door is already opened".
当其他线程正在等待它这样做时,倒计时闩锁可以“倒计时”,或者在这之前会导致“等待线程”永远不必等待,因为“门已经打开”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.