我使用ExecutorService创建了两个独立的线程。现在我只想要一个线程将数据写入文件,另一个线程将在从线程发送通知后读取它,该线程将数据写入文件,但输出没有显示任何内容,因此如何实现我的目标。 / p>
My code is:
package threadingexamples;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ThreadingExamples {
public static void main(String[] args) throws InterruptedException {
ExecutorService es = Executors.newFixedThreadPool(2);
es.submit(new ForLoo1());
es.submit(new ForLoop2());
es.shutdown();
es.awaitTermination(1, TimeUnit.DAYS);
System.exit(0);
}
}
class ForLoo1 implements Callable<Object> {
@Override
public Object call() throws Exception {
System.out.println("I am writing content into file....");
String s = "This is the content to write into a file";
File file = new File("/home/f.txt");
if (!file.exists()) {
file.createNewFile();
}
FileWriter fw = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(fw);
bw.write(s);
bw.close();
System.out.println("Now you can read content from files...");
notify();
return null;
}
}
class ForLoop2 implements Callable<Object> {
@Override
public Object call() throws Exception {
wait();
System.out.println("Okay i am now going to read content of files...");
BufferedReader br = new BufferedReader(new FileReader("f.txt"));
String str;
while ((str = br.readLine()) != null) {
str = str + "";
}
System.out.println("I am done with reading.....");
System.out.println(str);
return null;
}
}
答案 0 :(得分:2)
您可以使用以下代码达到预期效果。通过调用document.fileinfo.action = "<%=uploadJSP%>"
中的await
,线程只会在ForLoop2
中调用countDown
后唤醒。 CountDownLatch
是一种多功能的同步工具。
ForLoop1
答案 1 :(得分:0)
您可以使用Future来完成此操作。提交第一个任务会返回一个Future,第二个任务可以用来在任务完成后检索第一个任务的返回值;接收未来的Callable任务将阻塞,直到get方法收到结果。我更改了第一个callable以返回非null值:
package threadingexamples;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.Future;
public class ThreadingExamples {
public static void main(String[] args) throws InterruptedException {
ExecutorService es = Executors.newFixedThreadPool(2);
Future<Object> future = es.submit(new ForLoo1());
es.submit(new ForLoop2(future));
es.shutdown();
es.awaitTermination(1, TimeUnit.DAYS);
}
}
class ForLoo1 implements Callable<Object> {
@Override
public Object call() throws Exception {
System.out.println("I am writing content into file....");
String s = "This is the content to write into a file";
File file = new File("/home/f.txt");
if (!file.exists()) {
file.createNewFile();
}
FileWriter fw = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(fw);
bw.write(s);
bw.close();
System.out.println("Now you can read content from files...");
return "ok";
}
}
class ForLoop2 implements Callable<Object> {
private Future<Object> future;
public ForLoop2(Future<Object> future) {
this.future = future;
}
@Override
public Object call() throws Exception {
System.out.println("in ForLoop2, ");
Object ok = future.get();
System.out.println("Okay i am now going to read content of files...");
BufferedReader br = new BufferedReader(new FileReader("f.txt"));
String str;
while ((str = br.readLine()) != null) {
str = str + "";
}
System.out.println("I am done with reading.....");
System.out.println(str);
return null;
}
}
或者您可以使用BlockingQueue,将其传递到每个Callable的构造函数中。一个Callable将一个条目放入队列,另一个条目从中读取。这更适合于您希望在线程之间传递多条消息的情况。但是,原则相同:将等待/通知代码放在数据结构中,而不是放在任务中。
答案 2 :(得分:-1)
编辑:这是不该做的一个例子。请使用CountDownLatch
方法;在大多数程序中,您不需要使用notify
或wait
。另外,请阅读以下评论,了解为什么这是一个坏主意。即使添加了synchronized
块(需要调用notify
和wait
),仍然存在可能导致ForLoop2
死锁的竞争条件。
你几乎得到了它!当您在上面的代码中致电wait()
和notify()
时,他们会在不同的对象中被调用。试试这个:
Object monitorObject = new Object();
es.submit(new ForLoo1(monitorObject));
es.submit(new ForLoop2(monitorObject));
...
class ForLoop1 implements Callable<Object> {
private final Object monitorObject;
public ForLoop1(Object monitorObject) {
this.monitorObject = monitorObject;
}
@Override
public Object call() throws Exception {
...
synchronized(monitorObject) {
monitorObject.notify();
}
}
}
class ForLoop2 implements Callable<Object> {
private final Object monitorObject;
public ForLoop2(Object monitorObject) {
this.monitorObject = monitorObject;
}
@Override
public Object call() throws Exception {
synchronized(monitorObject) {
monitorObject.wait();
}
...
}
}