我们在平时的时候使用的是队列,指定好个数以后,如果放的数据超过了队列设定的个数的时候会报错误的。
那么多线程中,有一个阻塞队列的叫arrayBlockQueue。这个类是对queue在多线程中使用的扩展,
也就是说,当作为临界资源的时候,这个队列是安全,存放数据如果超过了队列设定好的初始的数据的时候,
放入数据的线程将会被等待着的。
下面来看例子。
场景模拟:
现在有两个线程,一个线程往队列里面添加数据,一个是将队列里面的数据取出来并且删掉数据。
当然,放数据的线程要速度快点,这样才能够模拟出来队列里面存放的数据的个数会超过队列起先设定好的初始的个数吧
存放的线程是每个 5 秒钟放一个数据,取得话是每个10秒钟 取一次,下面是代码 三个类:
main类
package endual;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 阻塞对列,往对立里面添加元素
* 一个由数组支持的有界阻塞队列。此队列按 FIFO(先进先出)
* 原则对元素进行排序。队列的头部 是在队列中存在时间最长的元素。
* 队列的尾部 是在队列中存在时间最短的元素。新元素插入到队列的尾部,
* 队列检索操作则是从队列头部开始获得元素。
*
*题目:
*两个操作队列,一个队列是取数据,一个队列是放数据,如果一个线程取放数据过快,那么对立会阻塞,
*线程也会进行等待着的
*
*
*/
public class ArrayBlockQueueApp {
public static void main(String[] args) {
ArrayBlockQueueApp app = new ArrayBlockQueueApp() ;
app.mian() ;
}
private void mian() {
ExecutorService es = Executors.newCachedThreadPool() ;
ArrayBlockingQueue<String> abq = new ArrayBlockingQueue<String>(10) ;
ThreadGet t1 = new ThreadGet(abq);
Thread t2 = new Thread(new ThreadPut(abq)) ;
es.execute(t1) ;
es.execute(t2) ;
}
}
get线程类
package endual;
import java.util.concurrent.ArrayBlockingQueue;
public class ThreadGet extends Thread{
ArrayBlockingQueue<String> abq = null ;
public ThreadGet(ArrayBlockingQueue<String> abq) {
this.abq = abq ;
}
public void run(){
while (true) {
try {
Thread.sleep(10000) ;
System.out.println("我要从队列中取数据了");
String msg = abq.remove() ;
System.out.println("队列里面取得的数据是:" + msg + " 队列中还的数据个数还有的 :" + abq.size());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}//每个十秒钟会进行拿数据出来的
}
}
}
取数据的线程类:
package endual;
import java.util.concurrent.ArrayBlockingQueue;
public class ThreadPut implements Runnable{
private ArrayBlockingQueue<String> abq = null ;
public ThreadPut (ArrayBlockingQueue<String> abq) {
this.abq = abq ;
}
public void run() {
while (true) {
try {
System.out.println("我要向队列里面存放数据了");
Thread.sleep(5000) ;
abq.put("1") ;
System.out.println("当前的队列里面存放的数据的个数是:" + abq.size());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} //向队列里面存放数据
}
}
}
下面是测试的结果:
我要向队列里面存放数据了
当前的队列里面存放的数据的个数是:1
我要向队列里面存放数据了
我要从队列中取数据了
队列里面取得的数据是:1 队列中还的数据个数还有的 :0
当前的队列里面存放的数据的个数是:1
我要向队列里面存放数据了
当前的队列里面存放的数据的个数是:2
我要向队列里面存放数据了
当前的队列里面存放的数据的个数是:3
我要向队列里面存放数据了
我要从队列中取数据了
队列里面取得的数据是:1 队列中还的数据个数还有的 :2
当前的队列里面存放的数据的个数是:3
我要向队列里面存放数据了
我要从队列中取数据了
队列里面取得的数据是:1 队列中还的数据个数还有的 :2
当前的队列里面存放的数据的个数是:3
我要向队列里面存放数据了
当前的队列里面存放的数据的个数是:4
我要向队列里面存放数据了
当前的队列里面存放的数据的个数是:5
我要向队列里面存放数据了
我要从队列中取数据了
队列里面取得的数据是:1 队列中还的数据个数还有的 :4
当前的队列里面存放的数据的个数是:5
我要向队列里面存放数据了
当前的队列里面存放的数据的个数是:6
我要向队列里面存放数据了
我要从队列中取数据了
队列里面取得的数据是:1 队列中还的数据个数还有的 :5
当前的队列里面存放的数据的个数是:6
我要向队列里面存放数据了
当前的队列里面存放的数据的个数是:7
我要向队列里面存放数据了
我要从队列中取数据了
队列里面取得的数据是:1 队列中还的数据个数还有的 :6
当前的队列里面存放的数据的个数是:7
我要向队列里面存放数据了
当前的队列里面存放的数据的个数是:8
我要向队列里面存放数据了
我要从队列中取数据了
队列里面取得的数据是:1 队列中还的数据个数还有的 :7
当前的队列里面存放的数据的个数是:8
我要向队列里面存放数据了
当前的队列里面存放的数据的个数是:9
我要向队列里面存放数据了
我要从队列中取数据了
队列里面取得的数据是:1 队列中还的数据个数还有的 :8
当前的队列里面存放的数据的个数是:9
我要向队列里面存放数据了
当前的队列里面存放的数据的个数是:10
我要向队列里面存放数据了
我要从队列中取数据了
队列里面取得的数据是:1 队列中还的数据个数还有的 :9
当前的队列里面存放的数据的个数是:10
我要向队列里面存放数据了
我要从队列中取数据了
当前的队列里面存放的数据的个数是:10
我要向队列里面存放数据了
队列里面取得的数据是:1 队列中还的数据个数还有的 :10
我要从队列中取数据了
当前的队列里面存放的数据的个数是:10
我要向队列里面存放数据了
队列里面取得的数据是:1 队列中还的数据个数还有的 :10
我要从队列中取数据了
当前的队列里面存放的数据的个数是:10
我要向队列里面存放数据了
队列里面取得的数据是:1 队列中还的数据个数还有的 :10
我要从队列中取数据了
当前的队列里面存放的数据的个数是:10
我要向队列里面存放数据了
队列里面取得的数据是:1 队列中还的数据个数还有的 :10
部分的结果。。。。。。
我们从结果中可以看出来,当队列里面的数据达到10个的时候,存放数据的线程在存放的时候将等待队列少的位子,不会像队列里面的数据少于10个的时候,存放数据是无需等待的,5秒钟到了就马上放进去。而到了10个数据的时候,存放的那个现在到了5秒钟的时候,还必须在等待位子,因为队列中还是10个位子,只有当取数据的线程取出数据以后,空出来的
位子后马上就添加进去了的