下面是有关线程运行生产者和消费者的代码。
public class PC1 {
public static final int limit = 3;
public static void main(String[] args) {
List bag = new ArrayList();
Producer p = new Producer(bag);
Consumer c = new Consumer(bag);
Thread t1 = new Thread(p, "t1");
Thread t2 = new Thread(c, "t2");
Thread t3 = new Thread(p, "t3");
Thread t4 = new Thread(c, "t4");
Thread t5 = new Thread(p, "t5");
Thread t6 = new Thread(c, "t6");
t2.start();
t4.start();
t6.start();
t1.start();
t3.start();
t5.start();
}
}
class Producer implements Runnable {
private List bag;
public Producer(List bag) {
this.bag = bag;
}
@Override
public void run() {
synchronized (bag) {
while (true) {
while (bag.size() >= PC1.limit) {
bag.notify();
System.out.println(Thread.currentThread().getName() + "@@@@@@@@@@@");
try {
bag.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int curr = bag.size();
bag.add(++curr);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " produce " + curr);
}
}
}
}
class Consumer implements Runnable {
private List bag;
public Consumer(List bag) {
this.bag = bag;
}
@Override
public void run() {
synchronized (bag) {
while (true) {
while (bag.size() <= 0) {
bag.notify();
System.out.println(Thread.currentThread().getName() + "!!!!!!!!!!!");
try {
bag.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int curr = bag.size();
bag.remove(curr - 1);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " consume " + (bag.size() + 1));
}
}
}
}
t2!!!!!!!!!!!!
t3 产生 1
t3 产生 2
t3 产生 3
t3@@@@@@@@@@@
t1@@@@@@@@@@@
t6消耗3
t6消耗2
t6消耗1
t6!!!!!!!!!!!!
t4!!!!!!!!!!!!
t6!!!!!!!!!!!!
t4!!!!!!!!!!!!
t6!!!!!!!!!!!!
t4!!!!!!!!!!!!
t6!!!!!!!!!!!!
t4!!!!!!!!!!!!
t6!!!!!!!!!!!!
t4!!!!!!!!!!!!
t6!!!!!!!!!!!!
t4!!!!!!!!!!!!
t6!!!!!!!!!!!!
t4!!!!!!!!!!!!
t6!!!!!!!!!!!!
t4!!!!!!!!!!!!
t6!!!!!!!!!!!!
t4!!!!!!!!!!!!
.
.
....一直这样t6和t4交替
上面是我控制台上的结果,可以看到:t2,t3,t1一开始就有机会执行,然后t6和t4交替,其他线程永远没有机会执行。
让我解释一下它的过程。
首先,t2获得消费权限,bag.size=0,等待
然后,t3获得生产权限,3次后,袋子已满,通知t2进入竞争状态,自行等待
然后,t1获得产品权限,由于袋子已满,通知t3使其进入竞争状态,自行等待
然后,t6获得消费权限,3次后,包为空,通知t3进入竞争状态,自行等待
然后t4获得消费权限,由于包为空,通知t6进入竞争状态,自行等待
.
.
.
我很困惑在t4等待之前,所有其他5个线程都处于竞争状态,但是结果显示只有t4和t6交替,其他线程永远没有机会执行。为什么会发生这种情况?
还有一个问题是,如果我将notify修改为notifyAll,那么6个线程都有机会执行。在我的理解中,如果多线程都处于竞争状态,那么它们都应该有机会执行。
最佳答案
通知工作正常;即根据其指定方式。 “问题”在于Java不保证wait/notify/notifyAll的公平调度。这意味着某些线程可能比其他线程承担更多的工作。
事实上,对于一个正常的程序来说,这并不重要:根本不是问题。例如,在普通的多线程生产者/消费者应用程序中,哪个消费者线程处理生产者生产的东西并不重要。重要的是它们得到有效处理。事实上,使用不公平的线程调度而不是公平的线程调度可能会带来性能优势。原因之一是可以减少线程上下文切换的次数。
<小时/>那么你将如何实现你的目标?
首先,不要使用wait/notify。如果您阅读这些方法的 javadoc,您会发现它们无法保证公平性。
获得公平性的一种方法是使用通过fair == true
实例化的ReentrantLock
;请参阅javadoc了解详情。
关于java - 只有 2 个线程用于调用生产和消费?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37136501/