由于工作需要,公司项目开始转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 }