NotifyAll 不工作
NotifyAll not working
此代码正在打印来自两个不同线程的 Even/Odd 数字。在这里,我的程序卡在 wait() 中,无法使用 notifyAll() 唤醒睡眠线程。
想知道为什么notifyAll无法唤醒所有休眠的线程?
需要知道我在这里做错了什么。
class EvenOddThread {
public static void main (String [] args) {
Runnable runnEven = new ThreadPrint (true, 10);
Runnable runnOdd = new ThreadPrint (false, 10);
Thread t1 = new Thread (runnEven);
Thread t2 = new Thread (runnOdd);
t1.start ();
t2.start ();
}
}
class ThreadPrint implements Runnable {
private boolean isEvenPrint = false;
private int maxPoint = 0;
ThreadPrint (boolean isEven, int max) {
isEvenPrint = isEven;
maxPoint = max;
}
@Override
public void run () {
Print p = new Print();
if (isEvenPrint)
p.printEven(maxPoint);
else
p.printOdd(maxPoint);
}
}
class Print {
public synchronized void printEven (int maxPoint) {
int even = 0;
while (even <= maxPoint) {
System.out.println(even);
even = even + 2;
try {
wait();
}
catch (Exception e) {
System.out.println(e);
}
notifyAll();
}
}
public synchronized void printOdd (int maxPoint) {
int odd = 1;
while (odd <= maxPoint) {
System.out.println(odd);
odd = odd + 2;
try {
wait();
}
catch (Exception e) {
System.out.println(e);
}
notifyAll();
}
}
}
谢谢,
希瓦姆
两个线程在打印第一个数字后都进入wait
。由于两个线程都已暂停,因此两个线程都无法唤醒另一个。
为了让一对线程以这种方式交替,您可以有单独的条件来控制每个线程的进度。每个线程在完成自己的工作单元后会解除对另一个线程的阻塞。这可以通过 Semaphore, CyclicBarrier, or Phaser.
来完成
notifyAll() 应该通知所有等待特定对象的线程,而不是所有在任何地方等待的线程。您所做的是,为每个线程创建一个 Print 实例 - 然后使用不合格的 wait()、notifyAll() - 这意味着您的线程使用每个线程的本地变量进行通信。
所以首先你必须让他们使用相同的 synchronization/signaling 个对象。
其次,您至少需要提供一些初始启动。在这里要小心,因为当您确定至少其中一个已经在收听时,您需要发出此信号。最好的情况是确保他们都在听,这样你就可以避免无数可能的竞争条件情况。
=咆哮=
Sun 在这里搞得一团糟,IMO,通过向程序员隐藏(互斥锁、条件、信号)三元组——很可能是为了使多线程更简单。他们失败了。
=/咆哮=
似乎您只需要两个线程以乒乓方式打印 odd/even 数字。然后你可以利用ReentrantLock
。有几种方法可以做到这一点。
我。锁
public static final ReentrantLock lock = new ReentrantLock();
public static final int LIMIT = 50;
public static int toPrint = 0;
public static void main(String[] args){
Thread t1 = new Thread(() -> {
while (true){
try {
lock.lock();
if(toPrint > LIMIT) break;
else if(toPrint % 2 == 0) {
System.out.println(toPrint++);
}
} finally {
lock.unlock();
}
}
});
Thread t2 = new Thread(() -> {
while (true) {
try {
lock.lock();
if (toPrint > LIMIT) break;
else if (toPrint % 2 == 1) {
System.out.println(toPrint++);
}
} finally {
lock.unlock();
}
}
});
t1.start();
t2.start();
}
二. Volatile(易碎,但有效)
public static final int LIMIT = 50;
public static volatile int toPrint = 0;
public static void main(String[] args){
Thread t1 = new Thread(() -> {
while (true){
int cur = toPrint;
if(cur > LIMIT) break;
else if(cur % 2 == 0){
System.out.println(cur);
toPrint = cur + 1;
}
}
});
Thread t2 = new Thread(() -> {
while (true) {
int cur = toPrint;
if(cur > LIMIT) break;
else if(cur % 2 == 1){
System.out.println(cur);
toPrint = cur + 1;
}
}
});
t1.start();
t2.start();
}
class EvenOddThread {
public static void main (String [] args) {
Runnable runnEven = new ThreadPrint (10);
Thread t1 = new Thread (runnEven);
Thread t2 = new Thread (runnEven);
t1.start ();
t2.start ();
}
}
class ThreadPrint implements Runnable {
private int maxPoint = 0;
private int counter = 0;
ThreadPrint (int max) {
maxPoint = max;
}
@Override
public void run () {
while (counter <= maxPoint) {
synchronized(this) {
if (counter % 2 == 0) {
System.out.println("By Thread" + Thread.currentThread().getName() +" :: "+ counter);
counter ++;
notify();
try {
wait();
}
catch (Exception e) {
System.out.println(e);
}
}
else if (counter % 2 != 0){
System.out.println("By Thread" + Thread.currentThread().getName() +" :: "+ counter);
counter ++;
notify();
try {
wait();
}
catch (Exception e) {
System.out.println(e);
}
}
}
}
}
}
谢谢大家的回答,但我得到了帮助
here 弄清楚我应该如何更正我的代码。
现在,它按照我想要的方式工作。 :)
此代码正在打印来自两个不同线程的 Even/Odd 数字。在这里,我的程序卡在 wait() 中,无法使用 notifyAll() 唤醒睡眠线程。
想知道为什么notifyAll无法唤醒所有休眠的线程? 需要知道我在这里做错了什么。
class EvenOddThread {
public static void main (String [] args) {
Runnable runnEven = new ThreadPrint (true, 10);
Runnable runnOdd = new ThreadPrint (false, 10);
Thread t1 = new Thread (runnEven);
Thread t2 = new Thread (runnOdd);
t1.start ();
t2.start ();
}
}
class ThreadPrint implements Runnable {
private boolean isEvenPrint = false;
private int maxPoint = 0;
ThreadPrint (boolean isEven, int max) {
isEvenPrint = isEven;
maxPoint = max;
}
@Override
public void run () {
Print p = new Print();
if (isEvenPrint)
p.printEven(maxPoint);
else
p.printOdd(maxPoint);
}
}
class Print {
public synchronized void printEven (int maxPoint) {
int even = 0;
while (even <= maxPoint) {
System.out.println(even);
even = even + 2;
try {
wait();
}
catch (Exception e) {
System.out.println(e);
}
notifyAll();
}
}
public synchronized void printOdd (int maxPoint) {
int odd = 1;
while (odd <= maxPoint) {
System.out.println(odd);
odd = odd + 2;
try {
wait();
}
catch (Exception e) {
System.out.println(e);
}
notifyAll();
}
}
}
谢谢, 希瓦姆
两个线程在打印第一个数字后都进入wait
。由于两个线程都已暂停,因此两个线程都无法唤醒另一个。
为了让一对线程以这种方式交替,您可以有单独的条件来控制每个线程的进度。每个线程在完成自己的工作单元后会解除对另一个线程的阻塞。这可以通过 Semaphore, CyclicBarrier, or Phaser.
来完成notifyAll() 应该通知所有等待特定对象的线程,而不是所有在任何地方等待的线程。您所做的是,为每个线程创建一个 Print 实例 - 然后使用不合格的 wait()、notifyAll() - 这意味着您的线程使用每个线程的本地变量进行通信。
所以首先你必须让他们使用相同的 synchronization/signaling 个对象。
其次,您至少需要提供一些初始启动。在这里要小心,因为当您确定至少其中一个已经在收听时,您需要发出此信号。最好的情况是确保他们都在听,这样你就可以避免无数可能的竞争条件情况。
=咆哮= Sun 在这里搞得一团糟,IMO,通过向程序员隐藏(互斥锁、条件、信号)三元组——很可能是为了使多线程更简单。他们失败了。 =/咆哮=
似乎您只需要两个线程以乒乓方式打印 odd/even 数字。然后你可以利用ReentrantLock
。有几种方法可以做到这一点。
我。锁
public static final ReentrantLock lock = new ReentrantLock();
public static final int LIMIT = 50;
public static int toPrint = 0;
public static void main(String[] args){
Thread t1 = new Thread(() -> {
while (true){
try {
lock.lock();
if(toPrint > LIMIT) break;
else if(toPrint % 2 == 0) {
System.out.println(toPrint++);
}
} finally {
lock.unlock();
}
}
});
Thread t2 = new Thread(() -> {
while (true) {
try {
lock.lock();
if (toPrint > LIMIT) break;
else if (toPrint % 2 == 1) {
System.out.println(toPrint++);
}
} finally {
lock.unlock();
}
}
});
t1.start();
t2.start();
}
二. Volatile(易碎,但有效)
public static final int LIMIT = 50;
public static volatile int toPrint = 0;
public static void main(String[] args){
Thread t1 = new Thread(() -> {
while (true){
int cur = toPrint;
if(cur > LIMIT) break;
else if(cur % 2 == 0){
System.out.println(cur);
toPrint = cur + 1;
}
}
});
Thread t2 = new Thread(() -> {
while (true) {
int cur = toPrint;
if(cur > LIMIT) break;
else if(cur % 2 == 1){
System.out.println(cur);
toPrint = cur + 1;
}
}
});
t1.start();
t2.start();
}
class EvenOddThread {
public static void main (String [] args) {
Runnable runnEven = new ThreadPrint (10);
Thread t1 = new Thread (runnEven);
Thread t2 = new Thread (runnEven);
t1.start ();
t2.start ();
}
}
class ThreadPrint implements Runnable {
private int maxPoint = 0;
private int counter = 0;
ThreadPrint (int max) {
maxPoint = max;
}
@Override
public void run () {
while (counter <= maxPoint) {
synchronized(this) {
if (counter % 2 == 0) {
System.out.println("By Thread" + Thread.currentThread().getName() +" :: "+ counter);
counter ++;
notify();
try {
wait();
}
catch (Exception e) {
System.out.println(e);
}
}
else if (counter % 2 != 0){
System.out.println("By Thread" + Thread.currentThread().getName() +" :: "+ counter);
counter ++;
notify();
try {
wait();
}
catch (Exception e) {
System.out.println(e);
}
}
}
}
}
}
谢谢大家的回答,但我得到了帮助 here 弄清楚我应该如何更正我的代码。
现在,它按照我想要的方式工作。 :)