所以我一直在使用Java中的简单等待/通知示例,由于某种原因,我无法让它正常运行。如果有人能够看到可能是什么问题,我将非常感激!
public class ThreadDemonstration
{
private String str = null;
Thread stringCreator = new Thread(new Runnable()
{
public void run()
{
synchronized(this)
{
str = "I have text";
notify();
}
}
});
private Thread stringUser = new Thread(new Runnable()
{
public void run()
{
synchronized(this)
{
if(str == null)
{
try {
System.out.println("str is null, I need help from stringCreator");
wait();
System.out.println(str);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
});
public static void main (String [] args)
{
ThreadDemonstration td = new ThreadDemonstration();
td.stringUser.start();
td.stringCreator.start();
}
}
我目前的输出是: str为null,我需要来自stringCreator的帮助
所以由于某种原因线程stringCreator没有唤醒stringUser或我完全错过了其他东西?
谢谢!
答案 0 :(得分:4)
您的块在不同对象上synchronized
。它们应该synchronized
超过一个公共对象,例如下面的monitor
对象:
public class ThreadDemonstration
{
private String str = null;
private final Object monitor = new Object();
Thread stringCreator = new Thread(new Runnable()
{
public void run()
{
synchronized(monitor)
{
str = "I have text";
monitor.notify();
}
}
});
private Thread stringUser = new Thread(new Runnable()
{
public void run()
{
synchronized(monitor)
{
while(str == null) //changed from if to while. This allows you to wait again if the thread gets woken up by something other than the appropriate notify.
{
try {
System.out.println("str is null, I need help from stringCreator");
monitor.wait();
//removed print statement from here
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
System.out.println(str); //added print statement here. str is guaranteed to not be null here.
}
}
});
为了避免为同步创建单独的对象,您可以使用synchronized(ThreadDemonstration.this)
或synchronized(ThreadDemonstration.class)
作为示例。
答案 1 :(得分:1)
试试这个:
private Thread stringUser = new Thread(new Runnable() {
//-----
System.out.println("str is null, I need help from stringCreator");
notify();
wait(100);
System.out.println(str);
//----
});
答案 2 :(得分:0)
您需要使用同一实例的wait
和notify
才能使其正常工作。由于您创建了两个不同的对象(Runnable
的2个实例),因此无效。我编写了一个使用两个不同类的简单示例,使用主类的实例作为内部锁。你也可以为我们设置一个“虚拟对象”(Object lock = new Object
)。
public class ThreadDemonstration {
private static String text;
public ThreadDemonstration(){
Thread user = new Thread(new StringUser(this));
Thread creator = new Thread(new StringCreator(this));
user.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
creator.start();
}
public class StringCreator implements Runnable{
private Object lock;
StringCreator(Object lock){
this.lock = lock;
}
@Override
public void run() {
synchronized(lock){
text = "Yeeeehaaaaa";
lock.notify();
}
}
}
public class StringUser implements Runnable{
private Object lock;
StringUser(Object lock){
this.lock = lock;
}
@Override
public void run() {
synchronized(lock){
if((text == null)){
System.out.println("I need help!");
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(text);
}
}
}
public static void main(String[] args){
new ThreadDemonstration();
}
}