生产者-消费者
轮训机制
//生产者与消费者 class Memory{ //内存 public static ArrayList<Integer> arr=new ArrayList<Integer>(); } public class Demo02 { public static void main(String[] args) { Random r=new Random(); new Thread(new Runnable() { //生产者 @Override public void run() { while(true){ //轮训 int temp=r.nextInt(10)+1; Memory.arr.add(temp); System.out.println("生产了:"+temp); //每隔100~900毫秒 int result=(r.nextInt(9)+1)*100; try { Thread.sleep(result); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }).start(); new Thread(new Runnable() { @Override public void run() { //消费者 while(true){ //轮训 try { Thread.sleep(800); //每隔800毫秒 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } for(int i:Memory.arr){ //一次性全部消费 System.out.println("消费了:"+i); } Memory.arr.clear(); } } }).start(); } }
轮训机制也很常用,设计的好也有很多应用场景
线程间的通知机制
wait(),notify()-(notifyAll())
wait和notify是object类的方法,也就是java为所有对象都提供了这两个方法。
wait和notify必须配合syn关键字使用。
wait释放锁,notify不释放锁。
先观察轮训
class ListAdd1 { private volatile static List<String> list=new ArrayList<String>(); public void add(){ list.add("oracle"); } public int size(){ return list.size(); } } public class Demo03 { public static void main(String[] args) { final ListAdd1 list1=new ListAdd1(); Thread t1=new Thread(new Runnable() { @Override public void run() { try { for(int i=0;i<10;i++){ list1.add(); System.out.println("当前线程:"+Thread.currentThread().getName()+"添加了一个元素.."); Thread.sleep(500); } } catch (InterruptedException e) { e.printStackTrace(); } } }, "t1"); Thread t2=new Thread(new Runnable() { @Override public void run() { while(true){ if(list1.size()==5){ System.out.println("当前线程收到通知:"+Thread.currentThread().getName()+" list size=5 线程停止.."); throw new RuntimeException(); } } } }, "t2"); t1.start(); t2.start(); } }
t2线程一直while(true),我们改进代码:
class ListAdd2 { private volatile static List<String> list=new ArrayList<String>(); public void add(){ list.add("oracle and java"); } public int size(){ return list.size(); } } public class Demo04 { public static void main(String[] args) { final ListAdd2 list2 = new ListAdd2(); //1、 实例化出来一个 lock //2、当使用wait 和 notify 的时候 , 一定要配合着synchronized关键字去使用 final Object lock = new Object(); //创建锁 Thread t1=new Thread(new Runnable() { @Override public void run() { try { synchronized (lock) { for(int i = 0; i <10; i++){ list2.add(); System.out.println("当前线程:"+Thread.currentThread().getName()+"添加了一个元素.."); Thread.sleep(500); if(list2.size()==5){ System.out.println("已经发出通知.."); lock.notify(); //不释放锁,t1执行完之后才会释放锁 } } } } catch (InterruptedException e) { e.printStackTrace(); } } }, "t1"); Thread t2 = new Thread(new Runnable() { @Override public void run() { synchronized (lock) { if(list2.size()!=5){ try { lock.wait(); //释放锁 } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("当前线程:"+Thread.currentThread().getName()+"收到通知线程停止.."); throw new RuntimeException(); } } }, "t2"); t2.start(); //先启动t2 t1.start(); } }
再次写一个生产者与消费者(不要拘泥具体代码)
//wait和notify必须配合synchronized关键字使用 class X{ public static List<Integer> list=new ArrayList<Integer>(); public static final Object lock = new Object(); //创建锁 } class Product implements Runnable{ Random r=new Random(); @Override public void run() { try { while(true){ synchronized (X.lock) { while(X.list.size()>=100){ X.lock.wait(); } int number=(r.nextInt(20)+1); //生产一个小余20的随机数 X.list.add(number); System.out.println("生产了:"+number); X.lock.notify(); } int temp=(r.nextInt(11))*100; Thread.sleep(temp); //每隔100~1000毫秒 } } catch (Exception e) { e.printStackTrace(); } } } class Consumer implements Runnable{ @Override public void run() { try { while(true){ synchronized (X.lock) { while(X.list.size()==0){ X.lock.wait(); } for(Integer i:X.list){ System.out.println("消费了"+i); } X.list.clear(); //清空 X.lock.notify(); } } } catch (Exception e) { e.printStackTrace(); } } } public class Demo11 { public static void main(String[] args) { new Thread(new Product()).start(); //生产者启动 new Thread(new Consumer()).start(); //消费者启动 } }