ArrayBlockingQueue是Java5中提供的阻塞队列,可以自定义阻塞队列的大小,有多种插入数据和取出数据的方法。每种方法执行时的效果不一样 具体看下图(JDK文档的截图):
/*
* 放入数据(阻塞模式)
* 1、put(e);(阻塞模式:如果队列中的数据容量已达上限,则处于阻塞状态 ,当队列中的容量小于上限值 则立即放入)
* 2、add(e);(非阻塞模式:如果队列中数据容量已达上限,则抛出异常)
* 3、offer(e);(非阻塞模式:如果队列中数据容量已达上限,则返回false)
* 4、offer(e, time, unit) 超时模式 如果单位时间内没有放入数据 则返回false
*/
/*
* 取出数据
* 1、take();(阻塞模式:如果队列中的没有数据,则处于阻塞状态 ,当队列中的一有数据 则立即取出)
* 2、remove();(非阻塞模式:如果队列中的没有数据,则抛出异常)
* 3、poll();(非阻塞模式:如果队列中的没有数据,则返回null)
* 4、poll(time, unit) 超时模式 如果单位时间内没有取出数据 则返回null
*/
ArrayBlockingQueue 应用示例代码:
import java.util.concurrent.ArrayBlockingQueue;
public class ArrayBlockingQueueTest
{
public static void main(String[] args)
{
//定义一个容量为3的阻塞队列
final ArrayBlockingQueue<Integer> queue =
new ArrayBlockingQueue<Integer>(3);
//开启两个线程用于向队列中存储数据
for(int i = 0; i < 2; i++)
{
new Thread(new Runnable()
{
@Override
public void run()
{
while(true)
{
try
{
Thread.sleep((long) (Math.random() * 100));
System.out.println("线程:" + Thread.currentThread().getName()
+ " 准备放数据...");
/*
* 放入数据(阻塞模式)
* 1、put(e);(阻塞模式:如果队列中的数据容量已达上限,则处于阻塞状态 ,当队列中的容量小于上限值 则立即放入)
* 2、add(e);(非阻塞模式:如果队列中数据容量已达上限,则抛出异常)
* 3、offer(e);(非阻塞模式:如果队列中数据容量已达上限,则返回false)
* 4、offer(e, time, unit) 超时模式 如果单位时间内没有放入数据 则返回false
*/
queue.put(1);
System.out.println("线程:" + Thread.currentThread().getName()
+ " 已经放入数据。队列中目前有:" + queue.size() + " 条数据。");
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
}
//开启一个线程 用于从队列中取数据
new Thread(new Runnable()
{
@Override
public void run()
{
while(true)
{
try
{
Thread.sleep((long) (Math.random() * 1000));
System.out.println("线程:" + Thread.currentThread().getName()
+ " 准备取数据...");
/*
* 取出数据
* 1、take();(阻塞模式:如果队列中的没有数据,则处于阻塞状态 ,当队列中的一有数据 则立即取出)
* 2、remove();(非阻塞模式:如果队列中的没有数据,则抛出异常)
* 3、poll();(非阻塞模式:如果队列中的没有数据,则返回null)
* 4、poll(time, unit) 超时模式 如果单位时间内没有取出数据 则返回null
*/
queue.take();
System.out.println("线程:" + Thread.currentThread().getName()
+ " 已经取出数据。队列中目前有:" + queue.size() + " 条数据。");
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}).start();
}
}
使用ArrayBlockingQueue实现线程间同步通信的功能
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class BlockingQueueCommunicationTest
{
static PrintInfo printer = new PrintInfo();
public static void main(String[] args)
{
Thread t1 = new Thread(new Runnable()
{
@Override
public void run()
{
for(int i = 0; i < 20; i++)
{
printer.printSubThread(i);
}
}
});
t1.start();
for (int i = 0; i < 20; i++)
{
printer.printMainThread(i);
}
}
}
class PrintInfo
{
/*
* 使用两个容量为1的阻塞队列 实现线程同步通信的功能
*/
BlockingQueue<Integer> queue1 = new ArrayBlockingQueue<Integer>(1);
BlockingQueue<Integer> queue2 = new ArrayBlockingQueue<Integer>(1);
/**
* 匿名构造方法
* 不管实例化对象时调用的是哪个构造方法 首先都会执行匿名构造方法
*/
{
try
{
//将queue2装满 为的是阻塞主线程
queue2.put(1);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
public void printSubThread(int loop)
{
try
{
queue1.put(1);
for(int i = 0; i < 20; i++)
{
System.out.println("Sub Thread Num:" + i + "#loop:" + loop);
}
//取出queue2的值 为了让主线程不再阻塞
queue2.take();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
public void printMainThread(int loop)
{
try
{
queue2.put(1);
for(int i = 0; i < 50; i++)
{
System.out.println("Main Thread Num:" + i + "#loop:" + loop);
}
//取出queue1的值 为了让子线程不再阻塞
queue1.take();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}