通知和等待代码场景
Notify and wait code scenario
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();
}
}
此处显示输出:-
i=0in t1
i=1in t4
Thread-0is running
Thread-1is notifying
notified
还应在输出中打印最后一行,即; “Thread-0 is waken up
”。为什么在打印 "notified" 之后它不会松开对线程 "t1 run() method " 的锁定并继续执行 t1 中 wait() 之后的代码。即它应该在打印 "notified".
之后打印 "Thread-0 is waken up"
你的synchronized
块有"no"效果。
您的 synchronized(this)
刚刚获得 Runnable
实例的锁,您还实现了 run
方法。
您的线程 t1
永远不会收到通知,它会等待您使用 wait()
方法的 Runnable
获得通知。唯一持有对此 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();
}
}
您正在锁定两个不同的对象。在您的示例中, "this" 指的是每个可运行实例。除此之外,变量"i"必须是volatile的(否则不同线程看不到最新的变化)
见下文:
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();
}
}
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();
}
}
您当前的问题是您同步了错误的(不同的)对象。正如您在代码中所说 "synchronized(this)" "this" 是当前线程实例。因为你有两个同步不会发生。
我真的建议用显示器思考。监视器是一种资源包装器,它以一种保持内部状态一致性的方式限制并发访问。我重新编写了您的代码以使用监视器。
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()" 现在在同一个对象上执行,因此执行线程将同步。
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();
}
}
此处显示输出:-
i=0in t1
i=1in t4
Thread-0is running
Thread-1is notifying
notified
还应在输出中打印最后一行,即; “Thread-0 is waken up
”。为什么在打印 "notified" 之后它不会松开对线程 "t1 run() method " 的锁定并继续执行 t1 中 wait() 之后的代码。即它应该在打印 "notified".
你的synchronized
块有"no"效果。
您的 synchronized(this)
刚刚获得 Runnable
实例的锁,您还实现了 run
方法。
您的线程 t1
永远不会收到通知,它会等待您使用 wait()
方法的 Runnable
获得通知。唯一持有对此 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();
}
}
您正在锁定两个不同的对象。在您的示例中, "this" 指的是每个可运行实例。除此之外,变量"i"必须是volatile的(否则不同线程看不到最新的变化)
见下文:
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();
}
}
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();
}
}
您当前的问题是您同步了错误的(不同的)对象。正如您在代码中所说 "synchronized(this)" "this" 是当前线程实例。因为你有两个同步不会发生。
我真的建议用显示器思考。监视器是一种资源包装器,它以一种保持内部状态一致性的方式限制并发访问。我重新编写了您的代码以使用监视器。
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()" 现在在同一个对象上执行,因此执行线程将同步。