public class NotifyAndWaitExample2 {
static int i = 0;
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (this) {
if (i <= 0) {
System.out.println("i=" + i + "in t1");
System.out.println(Thread.currentThread().getName() + "is running");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "is waken up");
}
}
});
Thread t4 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (this) {
i++;
System.out.println("i=" + i + "in t4");
System.out.println(Thread.currentThread().getName() + "is notifying");
try {
Thread.sleep(1000);
notify();
System.out.println("notified");
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
});
t1.start();
t4.start();
}
}
这里显示了ouptut: -
i=0in t1
i=1in t4
Thread-0is running
Thread-1is notifying
notified
最后一行也应印在输出中,即; &#34; Thread-0 is waken up
&#34 ;.为什么在印刷后通知&#34;&#34;它没有松散锁定线程&#34; t1 run()方法&#34;并在t1中的wait()之后继续执行代码。即它应该打印&#34;线程0被唤醒&#34;印刷后#34;通知&#34;。
答案 0 :(得分:2)
您的synchronized
块有“无”效果。
您的synchronized(this)
只获取Runnable
实例的锁定,您还可以在其中实施run
方法。
您的主题t1
将永远不会收到通知,它会等待您使用Runnable
方法的wait()
获得通知。保存对此Runnable的引用的唯一对象是Thread
对象t1
,并且(通常)不会在该Runnable上调用notify()
或notifyAll()
。
我使用int[]
来存储int值以及持有锁/监视器。解决方案只是向您展示如何做到这一点,并不意味着这样做是很好的做法。
我建议阅读一篇关于Java中的同步如何工作的好教程。
我已经修改了你的示例,以便它按预期工作。
public class NotifyAndWaitExample2 {
private static int[] i = {0};
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (i) {
if (i[0] <= 0) {
System.out.println("i=" + i[0] + " in t1");
System.out.println(Thread.currentThread().getName() + " is running");
try {
i.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " is waken up");
}
}
});
Thread t4 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (i) {
i[0]++;
System.out.println("i=" + i[0] + "in t4");
System.out.println(Thread.currentThread().getName() + " is notifying");
try {
Thread.sleep(1000);
i.notifyAll();
System.out.println("notifying");
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
});
t1.start();
t4.start();
}
}
答案 1 :(得分:1)
你锁定了两个不同的对象。在您的示例中,“this”指的是每个可运行的实例。除此之外,变量“i”必须是易失性的(否则,不同的线程将不会看到最新的变化)
见下文:
public class NotifyAndWaitExample {
private volatile int i = 0;
private Object lock1 = new Object();
public static void main(String[] args) {
NotifyAndWaitExample notifyAndWaitExample = new NotifyAndWaitExample();
notifyAndWaitExample.execute();
}
private void execute() {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock1) {
if (i <= 0) {
System.out.println("i= " + i + " in t1");
System.out.println(Thread.currentThread().getName() + " is running");
try {
lock1.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " is waken up");
}
}
});
Thread t4 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock1) {
i++;
System.out.println("i= " + i + " in t4");
System.out.println(Thread.currentThread().getName() + " is notifying");
try {
Thread.sleep(1000);
lock1.notify();
System.out.println("notified");
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
});
t1.start();
t4.start();
}
}
答案 2 :(得分:1)
public class NotifyAndWaitExample2 {
static int i = 0;
public static void main(String[] args) {
Object lock = new Object();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock) {
if (i <= 0) {
System.out.println("i=" + i + "in t1");
System.out.println(Thread.currentThread().getName() + "is running");
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "is waken up");
}
}
});
Thread t4 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock) {
i++;
System.out.println("i=" + i + "in t4");
System.out.println(Thread.currentThread().getName() + "is notifying");
try {
Thread.sleep(1000);
lock.notify();
System.out.println("notified");
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
});
t1.start();
t4.start();
}
}
答案 3 :(得分:1)
您当前的问题是您在错误的(不同的)对象上进行同步。正如您在代码中所说的“synchronized(this)”,“this”是当前的线程实例。因为你有两个同步不会发生。
我真的建议在监视器中思考。监视器是一个ressource包装器,它以一种保持内部状态一致性的方式限制并发访问。我重新制定了你的代码以使用监视器。
public class NotifyAndWaitExample2 {
private static class Monitor {
// Resource
private int i;
public synchronized void operation1() {
if (i <= 0) {
System.out.println("i=" + i + "in t1");
System.out.println(Thread.currentThread().getName() + "is running");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "is waken up");
}
public synchronized void operation2() {
i++;
System.out.println("i=" + i + "in t4");
System.out.println(Thread.currentThread().getName() + "is notifying");
try {
Thread.sleep(1000);
notify();
System.out.println("notified");
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
public static void main(String[] args) {
Monitor monitor = new Monitor();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
monitor.operation1();
}
});
Thread t4 = new Thread(new Runnable() {
@Override
public void run() {
monitor.operation2();
}
});
t1.start();
t4.start();
}
}
“wait()”和“notify()”现在在SAME对象上执行,因此执行的线程将被同步。