生产者-消费者模型的相关问题
来源:9-1 synchronized
慕斯6088333
2019-04-09
翔哥,您好,我刚听完第八章 和第九章的第一节。尝试着,写了一下producer-and-consumer 代码。
有几个问题,网上找了一些资料。有几个点还不是特别理解,求指导。
先上代码
package com.imooc.thread;
import java.util.LinkedList;
import java.util.List;
/**
* Single producer and consumer model
* @author tan3
*
*/
public class ProducerAndConsumer {
private static final List<Integer> BUFFER = new LinkedList<>();
private static final Integer BUFFER_MAX_SIZE = 3;
private static Integer productNum = 0;
private static final Integer ITERATION = 10;
public static void main(String[] args) {
final Object lock = new Object();
Thread producerThread = new Thread(new Runnable() {
@Override
public void run() {
// if the buffer is full, release the lock
synchronized(lock) {
for(int idx =0; idx < ITERATION ;idx++) {
if(BUFFER.size() == BUFFER_MAX_SIZE) {
try {
lock.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// if the buffer is not full, produce one good and wake up the consumer
try {
System.out.println(Thread.currentThread().getName()
+ " produce product: "+ productNum);
Thread.sleep(1000);
BUFFER.add(productNum++);
lock.notifyAll();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
},"Producer");
Thread consumerThread = new Thread(new Runnable() {
@Override
public void run() {
for(int idx =0; idx < ITERATION ;idx++) {
// if the buffer is empty, release the lock and wake up the producer
synchronized(lock) {
if(BUFFER.size() == 0) {
try {
lock.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// if the buffer is not empty, produce one good and tell the consumer to produce one
try {
System.out.println(Thread.currentThread().getName()
+ " consume product: "+ BUFFER.remove(0));
Thread.sleep(1000);
lock.notifyAll();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
},"Consumer");
producerThread.start();
consumerThread.start();
/*try {
producerThread.join();
consumerThread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
*/
}
}
几个疑惑的点。
-
我这里用的是if(BUFFER.size() == BUFFER_MAX_SIZE) if语句进行判断的。网上说应该是用while 语句。 【在多线程中要测试某个条件的变化,使用if 还是while】 , 我测试了一下,我的程序跑了几遍。好像没出什么问题。(但是好像网上搜到的更多的是使用wait方法)。想知道这个地方到底该怎么理解。
-
https://www.geeksforgeeks.org/producer-consumer-solution-using-threads-java/
第二问题是关于join方法的。这个答案,最后用了join方法来确保生产线程 finishes before 消费者线程。(我试了一下,好像没什么用。)似乎这里不涉及抢占资源的问题吖?) -
如果扩展multiple consumer and multiple producer,是不是BUFFER改成violate。以及voilate 是不是不可以跟final 并用。这里是用final 还是voilate。 怎么保证线程安全。我觉得final 就是保证线程安全比较好的方式了。。
可能概念有点多。学得越多越糊涂了。希望和大家探讨。
2回答
-
同学好,我一个个问题回答哈
现在只有一个生产者,使用if是没问题的,如果存在多个生产者的话,是会多生产的,此时需要使用while,因为调用wait之后被唤醒是会接着执行的。
代码里其实已经决定哪个线程先执行完了,所以不需要join方法。
使用final是不能保证安全的,多个生产者或消费者的话,每次也只有一个能获取到对象锁,直接用现在这种写法就可以,无非就是多起几个线程。
132019-04-10 -
慕斯6088333
提问者
2019-04-10
我发现翔哥,你公开课讲的deadlock demo 。我尝试着加了语句,解开dead lock 。我以为先后顺序是用join方法控制,确保线程1把锁释放,让线程2拿到锁,然后让线程2执行完,结束生命周期前唤醒线程1,然后线程1自然而然有了b的锁。。到底是线程1还是2先执行完取决于谁调用wait方法和执行前后顺序有关。那么join到底啥时候用啊
package com.imooc.thread; public class DeadLockDemo { public static void main(String[] args) { final Object lockA = new Object(); final Object lockB = new Object(); Thread t1 = new Thread( new Runnable() { @Override public void run() { // TODO Auto-generated method stub String name = Thread.currentThread().getName(); synchronized(lockA) { System.out.println(name +" got lock A, waiting to get lock B"); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { lockA.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } synchronized(lockB) { System.out.println(name +" got lock B"); System.out.println(name+"finish"); } } } },"Thread A"); Thread t2 = new Thread( new Runnable() { @Override public void run() { // TODO Auto-generated method stub String name = Thread.currentThread().getName(); synchronized(lockB) { System.out.println(name +" got lock B, waiting to get lock A"); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } synchronized(lockA) { System.out.println(name +" got lock A"); System.out.println(name+"finish"); lockA.notifyAll(); } } } },"Thread B"); t1.start(); /*try { Thread.sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }*/ t2.start(); } }
022019-04-10
相似问题