关于线程同步问题,最经典的案例就是“生产者与消费者的同步问题"了,消费者和生产者之间可以有一个缓冲区,为什么要有这个缓冲区呢?
缓冲区就相当于我们平时逛的商场,便利店之类的地方,充当一个中间人的角色,生产者生产出来的产品可以直接丢给中间人,不用去等待消费者去消费,一定程度上实现了程序之间的解耦,和防止线程阻塞带来的效率问题。
这里简要说一下他们之间的关系:
①生产者在没有产品的时候开始生成,消费者等待
②消费者在产品满的时候开始消费,生产者等待
消费者在没有产品的时候会通知生产者生产
生产者在产品满的时候通知消费者进行消费
实现生产者与消费者模型,有三种方式:
一 使用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(); } } } }