gpt4 book ai didi

java - 调用notify并不会唤醒其他等待线程

转载 作者:行者123 更新时间:2023-11-30 04:07:16 25 4
gpt4 key购买 nike

我有两个线程,T1 和 T2。两者都有自己的数组列表,我想从 T1 中删除数组列表的一个元素,删除后,我希望它想要直到 T2 数组列表元素也删除

所以流程应该是这样的:

t1 remove element
t2 remove element

t1 remove element
t2 remove element
.
.
.

这是我的代码:

import static java.lang.Thread.sleep;
import java.util.ArrayList;

public class ThreadsTest {

public static void main(String[] args) {
Thread t1 = new Thread(new T1());
t1.start();

Thread t2 = new Thread(new T2());
t2.start();
}
}

class T1 implements Runnable {

private ArrayList<String> list;

public T1() {
list = new ArrayList();
list.add("t1 1");
list.add("t1 2");
list.add("t1 3");
list.add("t1 4");
list.add("t1 5");
}

@Override
public void run() {
while (!list.isEmpty()) {
System.out.println(list.remove(0));
try {
synchronized (this) {
wait();
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}

}

class T2 implements Runnable {

private ArrayList<String> list;

public T2() {
list = new ArrayList();
list.add("t2 1");
list.add("t2 2");
list.add("t2 3");
list.add("t2 4");
list.add("t2 5");
}

@Override
public void run() {
while (!list.isEmpty()) {
System.out.println(list.remove(0));
try {

synchronized (this) {
notifyAll();
sleep(1000);
}

} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}

}

为什么调用notify并不能唤醒T1?以及如何修复它?

最佳答案

您的代码中有 2 个问题:

首先,您正在同步/等待监视器“this”,这是实际的对象,因此对于 T1,它是 T1,对于 T2,它是 T2。为了正确地做到这一点,两个线程需要在同一个对象上同步/等待。执行此操作的常见方法是专门创建这样的对象:

final static Object monitor = new Object();

请注意,final 关键字在这里很重要,您不想在中间意外更改监视器。

但即使您这样做,也不能保证在 T2 调用 notifyAll() 期间 T1 已经在等待,因为线程的执行顺序未定义。实际上,这可能会导致 T1 在删除后的最后一个等待调用期间死锁,因为 T2 已经完成。

编辑:如何使用 Phaser 执行此操作

声明两个线程都可以使用的 Phaser 实例:

static final Phaser phaser = new Phaser(2); // 2 threads = 2 parties

T1的run方法变为:

while (!list.isEmpty()) {
System.out.println(list.remove(0));
phaser.arriveAndAwaitAdvance();
phaser.arriveAndAwaitAdvance();
}
phaser.arriveAndDeregister();

T2的run方法变为:

while (!list.isEmpty()) {
phaser.arriveAndAwaitAdvance();
System.out.println(list.remove(0));
phaser.arriveAndAwaitAdvance();
}
phaser.arriveAndDeregister();

在这种情况下,取消注册不是必需的,而是作为一种安全机制:一旦取消注册,系统就可以继续,而无需刚刚完成的线程。

关于java - 调用notify并不会唤醒其他等待线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20440485/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com