多线程学习之路-学习wait和notify
由于工作需要,公司项目开始转Java,大部分东西需要自学来完成,之前在网上看过好多视频教程,其中有个作业是使用 wait notify 实现一个队列,队列有2个方法,put 和 take 。put方法往队列中添加元素,take方法往队列中获得元素。
队列必须是线程安全的。如果put执行时,队列为空,线程必须阻塞等待,直到有队列有数据。如果put时,队列已经满,则put线程要等待,直到队列有空闲空间。网上找了好多答案,好多答案都是使用 ArrayBlockingQueue<Integer>实现的,
感觉都不是很符合这个题目的要求,索性自己就摸索着
写了一个例子;先说一下解题思路
1.首先定义一个普通的Java类
2.既然是队列里面必须申请一个list对应,这里我用了LinkedList实现了List接口;
3.定义了List,就需要对list有添加和移除的方法,因此产生了put和take的两个方法;put中判断长度,大于定义长度则wait;小于则添加并且notify其他线程;take操作类似;
4.多线程操作,肯定需要一个对象锁,因此声明了类型为Object的lock锁;
5.作为设置了List最大长度,因此申明了AtomicInteger的count对象,此时为啥不用list.size()获取长度,因为多线程的操作size没有同步功能;
大概思路就是这样,下面直接上代码,代码可以直接运行的;内容是根据网络视频写的,欢迎大家转载学习交流;
1 package threadtest; 2 3 import java.util.LinkedList; 4 import java.util.concurrent.TimeUnit; 5 import java.util.concurrent.atomic.AtomicInteger; 6 7 public class QueueTest01 { 8 private LinkedList<Object> list = new LinkedList<Object>(); 9 private AtomicInteger count = new AtomicInteger(0); 10 private final int minSize = 0; 11 private final int maxSize; 12 13 public QueueTest01(int maxsize) { 14 this.maxSize = maxsize; 15 } 16 17 private final Object lock = new Object(); 18 19 public void put(Object obj) { 20 synchronized (lock) { 21 while (this.maxSize == count.get()) { 22 try { 23 lock.wait(); 24 } catch (InterruptedException e) { 25 // TODO Auto-generated catch block 26 e.printStackTrace(); 27 } 28 } 29 list.add(obj); 30 count.incrementAndGet(); 31 System.out.println("新加入的元素是:" + obj); 32 lock.notify(); 33 } 34 } 35 36 public Object take() { 37 Object obj = null; 38 synchronized (lock) { 39 while (this.minSize == count.get()) { 40 try { 41 lock.wait(); 42 } catch (InterruptedException e) { 43 // TODO Auto-generated catch block 44 e.printStackTrace(); 45 } 46 } 47 obj = list.removeFirst(); 48 count.decrementAndGet(); 49 lock.notify(); 50 } 51 return obj; 52 } 53 54 public static void main(String[] args) { 55 final QueueTest01 myQueue = new QueueTest01(5); 56 myQueue.put("a"); 57 myQueue.put("b"); 58 myQueue.put("c"); 59 myQueue.put("d"); 60 myQueue.put("e"); 61 System.out.println("当前对列的长度:" + myQueue.list.size()); 62 63 Thread t1 = new Thread(new Runnable() { 64 65 @Override 66 public void run() { 67 myQueue.put("f"); 68 myQueue.put("g"); 69 } 70 }, "t1"); 71 t1.start(); 72 Thread t2 = new Thread(new Runnable() { 73 74 @Override 75 public void run() { 76 Object o1 = myQueue.take(); 77 System.out.println("移除的元素为:" + o1); 78 Object o2 = myQueue.take(); 79 System.out.println("移除的元素为:" + o2); 80 } 81 }, "t2"); 82 try { 83 TimeUnit.SECONDS.sleep(2); 84 } catch (InterruptedException e) { 85 // TODO Auto-generated catch block 86 e.printStackTrace(); 87 } 88 t2.start(); 89 90 } 91 }