关于线程同步问题,最经典的案例就是“生产者与消费者的同步问题"了,消费者和生产者之间可以有一个缓冲区,为什么要有这个缓冲区呢?
缓冲区就相当于我们平时逛的商场,便利店之类的地方,充当一个中间人的角色,生产者生产出来的产品可以直接丢给中间人,不用去等待消费者去消费,一定程度上实现了程序之间的解耦,和防止线程阻塞带来的效率问题。
这里简要说一下他们之间的关系:
①生产者在没有产品的时候开始生成,消费者等待
②消费者在产品满的时候开始消费,生产者等待
消费者在没有产品的时候会通知生产者生产
生产者在产品满的时候通知消费者进行消费
实现生产者与消费者模型,有三种方式:
一 使用synchronized关键字,传递参数产品,表示在生产或消费的时候,另一方不能进行操作
wait()、notifiyall()方法是实现线程间的通信
二 在生产和消费方法上加上synchronized关键字,变成同步方法,同步对象是产品类本身,
也是使用wait()、notifyAll()方法实现线程间的通信,需要注意的是wait()和 notifyall()的条件
三 使用lock、condition 实现
await()方法和signalall()方法实现线程间的通讯,同样要注意方法的条件
方式1:
package produceComsumer;
import java.util.ArrayList;
/**
* Created on 10:59 02/09/2019
* Description:
*
* @author Weleness
*/
public class Producer {
public Object obj;
public ArrayList<Integer> list;//用list存放生产之后的数据,最大容量为1
public Producer(Object obj, ArrayList<Integer> list) {
this.obj = obj;
this.list = list;
}
public void prodece(){
synchronized (obj){
while (!list.isEmpty()){
System.out.println("生产者"+Thread.currentThread().getName()+"waiting");
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int value = 9999;
list.add(value);
System.out.println("生产者"+Thread.currentThread().getName()+"Runnable");
obj.notifyAll();
}
}
}
package produceComsumer;
import java.util.ArrayList;
/**
* Created on 11:15 02/09/2019
* Description:
*
* @author Weleness
*/
public class Comsumer {
private Object obj;
private ArrayList<Integer> list;
public Comsumer(Object obj, ArrayList<Integer> list) {
this.obj = obj;
this.list = list;
}
public void comsuemr(){
synchronized (obj){
while (list.isEmpty()){
System.out.println("消费者"+Thread.currentThread().getName()+"waiting");
try {
obj.wait();//手动释放obj锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.clear();
System.out.println("消费者"+Thread.currentThread().getName()+"Runnable");
obj.notifyAll();//唤醒所有在这个锁上阻塞的线程
}
}
}
方式2:
package produceComsumer;
import java.util.ArrayList;
import java.util.Collections;
/**
* Created on 11:36 02/09/2019
* Description:
*
* @author Weleness
*/
public class MyService {
private ArrayList<Integer> list;
public MyService(ArrayList<Integer> list) {
this.list = list;
Collections.synchronizedList(list);
}
synchronized void produce() {
while (list.size()!=0) {
try {
System.out.println(Thread.currentThread().getName() + "waiting");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
int value = 9999;
list.add(value);
System.out.println(Thread.currentThread().getName()+"Runnable");
notifyAll();
}
}
synchronized void comsumer() {
while (list.size()==0){
try {
System.out.println(Thread.currentThread().getName()+"waiting");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.clear();
System.out.println(Thread.currentThread().getName()+"Runnable");
this.notifyAll();
}
}
package produceComsumer;
/**
* Created on 11:43 02/09/2019
* Description:
*
* @author Weleness
*/
public class ComsumerThraed2 extends Thread {
private MyService ms;
public ComsumerThraed2(MyService ms) {
this.ms = ms;
}
public void run(){
while (true){
ms.comsumer();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package produceComsumer;
/**
* Created on 11:36 02/09/2019
* Description:
*
* @author Weleness
*/
public class ProduceThread2 extends Thread{
private MyService ms ;
public ProduceThread2(MyService ms) {
this.ms = ms;
}
public void run(){
while (true){
ms.produce();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
方式3:
package produceComsumer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* Created on 15:48 02/09/2019
* Description:
*
* @author Weleness
*/
public class MyServiceLcok {
private ReentrantLock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private boolean hasValue = false;
public void produce(){
lock.lock();
try {
while (hasValue==true){
System.out.println(Thread.currentThread().getName()+"waiting");
condition.await();
}
hasValue = true;
System.out.println(Thread.currentThread().getName()+"Runnable");
condition.signalAll();
}
catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void comsumer(){
lock.lock();
try {
while (hasValue==false){
System.out.println(Thread.currentThread().getName()+"waiting");
condition.await();
}
hasValue=false;
System.out.println(Thread.currentThread().getName()+"Runnable");
condition.signalAll();
}catch (InterruptedException e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
package produceComsumer;
/**
* Created on 15:54 02/09/2019
* Description:
*
* @author Weleness
*/
public class ProduceThreadLock extends Thread {
private MyServiceLcok p;
public ProduceThreadLock(MyServiceLcok p) {
this.p = p;
}
@Override
public void run() {
while (true){
p.produce();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package produceComsumer;
/**
* Created on 15:55 02/09/2019
* Description:
*
* @author Weleness
*/
public class ComsumerThreadLock extends Thread {
private MyServiceLcok c ;
public ComsumerThreadLock(MyServiceLcok c) {
this.c = c;
}
@Override
public void run() {
while (true){
c.comsumer();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
参考文章
https://blog.csdn.net/u011109589/article/details/80519863