[英]Why does it matter what object I use wait()/notify() on, if I just want a way to signal between threads?
所以我有一个经典案例“我的代码可行,但我不知道为什么”。
我有一个创建线程的程序,当我从扫描仪接收到某个输入时,我将字符串的控制权传递给工作线程。 为此,我创建了我的线程wait(),当我从UI线程获得正确的输入时,我通知()。
这是我的代码。 为简单起见,我刚刚使用了一个线程。
package main;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
class ThreadDemo extends Thread {
private Thread t;
private String threadName;
volatile Boolean keepRunning = true;
private Queue<String> q = new LinkedList<String>();
ThreadDemo( String name){
threadName = name;
System.out.println("Creating " + threadName );
}
public void in(String ex){
q.add(ex);
System.out.println("Added " + ex + "to queue of " + threadName);
synchronized(t){
t.notify();
}
}
public void run() {
System.out.println("Starting to loop.");
while (keepRunning) {
try {
//Why does it matter that I synchronized t?
synchronized(t){
System.out.println(threadName + "Waiting");
t.wait();
}
} catch (InterruptedException e) {
System.out.println("Thread interrupted " + e.toString());
}
System.out.println(threadName + "notified");
if (q.size()>0){
String out = q.remove();
System.out.println(threadName + "received " + out);
}
}
System.out.println("Done looping.");
}
public void start ()
{
System.out.println("Starting " + threadName );
if (t == null)
{
t = new Thread (this, threadName);
t.start ();
}
}
}
public class DataAnalysisProgram {
public static void main(String[] args) {
ThreadDemo T1 = new ThreadDemo( "Thread-1");
T1.start();
System.out.println("say something");
Scanner s = new Scanner(System.in);
String t;
do{
t = s.next();
T1.in(t);
}while (!t.equals("stop"));
T1.keepRunning = false;
T1.interrupt();
s.close();
}
}
所以这很好。 我的线程一直等到我使用notify。 但是,我真的不明白我称之为notify
和wait
对象的重要性。
在我的实现中,我不知道做了t.wait()/t.notify()
,其中t是我的线程对象。 我想如果我做了threadName.wait()/threadName.notify()
它仍然可以工作。 为什么我们调用notify并等待看似随意的对象? 我知道我在这里错过了关于通知和等待的概念。
实际上,当您在Thread
实例上调用wait
时,您违反了合同:
建议应用程序不要在
Thread
实例上使用wait
,notify
或notifyAll
。
这是因为Thread
将其用于内部目的。
回答你的问题: Thread
对象不是一个线程 。 说t.notify()
不通知t
,它通知在t
的监视器上等待的线程。 在此上下文中, Thread
的实例只是另一个Java对象,所有Java对象都有一个与之关联的监视器。
您建议使用String threadName
的监视器是另一个坏主意,因为您不控制字符串实例的生命周期,并且可能很容易践踏内部字符串的问题。
建议不要在线程协调中涉及任意对象的监视器,但更喜欢使用Object
专用实例。 这是由于关注点分离原则的一般优点所促成的。
为什么我们调用notify并等待看似随意的对象?
调用wait和notify对对象本身没有直接影响,所以它确实是任意的。 您所需要的只是一些可以用作通信点的对象。
实际上,有人认为Java语言中的历史错误是可以对任意对象使用wait和notify,因为管理锁会给所有对象增加很小的成本和复杂性,即使对于绝大多数对象来说也是如此没用了。 相反,他们应该使用专用的Lock类,或者让对象实现特定的接口,以指示您可以对它们调用wait / notify或类似的东西。
无论如何, 不使用任意对象是一个好主意,因为(a)它令人困惑,(b)它可能会与可能试图使用同一对象的其他代码纠缠在一起。 如果没有合理的对象,您应该为此目的创建一个:
private final Object lock = new Object();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.