创建两个Runnable,其中一个的run()方法启动并调用wait(),第二个Runnable中run()方法在一定的几秒之后,为第一个任务调用notify(),从而使得第一个Runnable能显示一条信息,用Executor来测试。
public class RunnableWait implements Runnable{
public Object obj=new Object();
@Override
public void run() {
synchronized (obj)
{
System.out.println(Thread.currentThread()+"开始等待"+obj);
try
{
obj.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread()+"等待结束!"+obj);
}
}
public Object getLock()
{
return obj;
}
}
import java.util.concurrent.TimeUnit;
public class RunnableNotify implements Runnable{
private RunnableWait rwait=new RunnableWait();
private Object obj=rwait.getLock();
@Override
public void run()
{
synchronized (obj)
{
try
{
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread()+"唤醒rwait!"+obj);
obj.notifyAll();
System.out.println(Thread.currentThread()+"唤醒结束!"+obj);
}
}
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExecutorMain {
public static void main(String[] args) {
ExecutorService exe =Executors.newCachedThreadPool();
exe.execute(new RunnableWait());
exe.execute(new RunnableNotify());
exe.shutdown();
}
}
会发现RunnableWait的wait()无法被唤醒。
原因:在RunnableNotify中由rwait.getLock()获得的Object对象已经与在ExecutorMain 类执行的exe.execute(new RunnableWait())的RunnableWait对象中产生的Object对象不同。换言之,RunnableNotify中的同步对象锁obj与RunnableWait中的对象锁不为同一个对象。所以也就导致的在RunnableNotify中的run()中的同步代码块中obj.notify()无法唤醒RunnableWait中的obj.wait()。
验证:把RunnableNotify中
System.out.println(Thread.currentThread()+"唤醒rwait!"+obj);
变成
System.out.println(Thread.currentThread()+"唤醒rwait!"+obj+"/"+rwait.getLock());
结果:
解决方法
①:把RunnableWait中的obj设置为public static,删除getLock()方法,在RunnableNotify中直接由类获取RunnableWait中的obj。
代码:
public class RunnableWait implements Runnable{
public static Object obj=new Object();
@Override
public void run() {
synchronized (obj)
{
System.out.println(Thread.currentThread()+"开始等待"+obj);
try
{
obj.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread()+"等待结束!"+obj);
}
}
}
import java.util.concurrent.TimeUnit;
public class RunnableNotify implements Runnable{
private Object obj=RunnableWait.obj;
@Override
public void run()
{
synchronized (obj)
{
try
{
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread()+"唤醒rwait!"+obj);
obj.notifyAll();
System.out.println(Thread.currentThread()+"唤醒结束!"+obj);
}
}
}
ExecutorMain类不变。
②在创建RunnableWait类时构造函数定义为
public RunnableWait(Object obj)
{
this.obj=obj;
}
RunnableNotify也如此,
public RunnableNotify(Object obj)
{
this.obj=obj;
}
在ExecutorMain中创建obj对象引用,执行时:
exe.execute(new RunnableWait(obj));
exe.execute(new RunnableNotify(obj));
③在RunnableNotify的构造方法中获取RunnableWait的对象引用