1.阻塞队列
(1)什么是阻塞队列?
可以在多线程环境下安全使用,并且支持阻塞、等待的队列。
注:阻塞、等待指的是当队列满的时候会阻塞生产者线程,直到队列不满;
当队列为空的时候会阻塞消费者线程,直到队列不空。
(2)阻塞队列的使用
BlockingQueue接口,LinkedBlockingQueue是该接口的一个实现类。
练习1:
写一个生产者消费者模型,要求如下:
a.阻塞队列只能存放10个元素
b.生产者每隔1秒向阻塞队列中添加一个随机数,消费者每隔20秒从阻塞队列中获取
随机数然后在控制台输出。
参考代码:
/**
* 生产者
*/
public class Producer implements Runnable{
private BlockingQueue<Integer> bq;
public Producer(BlockingQueue bq) {
this.bq = bq;
}
@Override
public void run() {
Random rd = new Random();
while (true){
int number = rd.nextInt(1000);
System.out.println("生产者线程向阻塞队列中写入一个随机数:"
+ number);
try {
bq.put(number);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 消费者
*/
public class Consumer implements Runnable{
private BlockingQueue<Integer> bq;
public Consumer(BlockingQueue bq) {
this.bq = bq;
}
@Override
public void run() {
while (true){
try {
int number = bq.take();
System.out.println("消费者线程从阻塞队列中获取一个随机数:"+ number);
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Test {
public static void main(String[] args) {
BlockingQueue<Integer> bq =
new LinkedBlockingQueue<>(10);
Producer p = new Producer(bq);
Consumer c = new Consumer(bq);
new Thread(p).start();
new Thread(c).start();
}
}
练习2: 写一个日志工具类
参考代码:
/**
* 记日志的工具类
*/
public class Logger {
//bq用于存放日志信息
private BlockingQueue<String> bq;
//out指向日志文件
private PrintWriter out;
/**
* open方法为记日志做一些准备工作。
*
*/
public void open() throws FileNotFoundException {
//1.创建一个阻塞队列
bq = new LinkedBlockingQueue<>(1000);
//2. 打开日志文件
out = new PrintWriter("logger.txt");
//3. 启动记日志的线程
Thread t = new Thread(){
@Override
public void run() {
while(true){
try {
System.out.println("从阻塞队列中读取日志信息...");
//从阻塞队列中读取日志信息
String info = bq.take();
//将日志信息写到日志文件里面
out.println(info);
System.out.println("将日志信息:" + info + "写入日志文件了");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
//启动记日志的线程
t.start();
}
/**
* 记日志方法
* @param info 日志信息
*/
public void log(String info){
try {
System.out.println("开始向阻塞队列中写入日志信息...");
//将日志信息写到阻塞队列里面就可以了
bq.put(info);
System.out.println("日志信息“ + info + ”写入阻塞队列完毕");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 关闭日志文件
*/
public void close(){
if(out != null){
out.close();
}
}
}
public class LoggerTest {
public static void main(String[] args) throws FileNotFoundException {
Logger logger = new Logger();
logger.open();
logger.log("Hello Kitty");
logger.log("balabala");
logger.log("hehehe");
logger.log("heihei");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.close();
}
}