这里是一个应用项目使用生产消费模型的日志类
package cn.study.concurrency; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import org.junit.Test; /** * 日志服务 * @author xiaof * */ public class LogWriter { private final BlockingQueue<String> queue; private final LoggerThread logger; private final static int CAPACITY = 500; private boolean isShutdown; //停止线程 public LogWriter() { this.queue = new LinkedBlockingQueue<String>(CAPACITY); this.logger = new LoggerThread(); } public void start() { //判断这个线程是否已经启动 if(!logger.isAlive()) { logger.start(); } } public void log(String msg) throws InterruptedException { //放入日志队列并阻塞队列 if(!isShutdown) queue.put(msg); else throw new IllegalStateException("日志开关没有打开"); } public boolean isShutdown() { return isShutdown; } public void setShutdown(boolean isShutdown) { this.isShutdown = isShutdown; } private class LoggerThread extends Thread { public void run() { try { while(true) { //从队列中取出队列头数据,并输出,有必要并阻塞队列 System.out.println("这是日志:" + queue.take()); } } catch (Exception e) { e.printStackTrace(); } } } @Test public void test() { LogWriter log = new LogWriter(); log.start(); int i = 1; while(true) { try { Thread.currentThread().sleep(2000); //把日志放入队列 log.log("这是日志:" + i++); if(i == 3) { log.setShutdown(true); } } catch (InterruptedException e) { e.printStackTrace(); } } } }
更加可靠的取消日志服务的操作
package cn.study.concurrency; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import org.junit.Test; /** * 日志类添加可靠的取消操作 * @author xiaof * */ public class LogService { private final BlockingQueue<String> queue; private final LoggerThread loggerThread; private boolean isShutdown; //如果线程停止提交任务,线程不能停,先得吧剩余的任务提交结束 private int reservations; private final static int CAPACITY = 500; public LogService() { //队列长度 this.queue = new LinkedBlockingQueue<String>(CAPACITY); this.loggerThread = new LoggerThread(); } public void start() { //判断这个线程是否已经启动 if(!loggerThread.isAlive()) { loggerThread.start(); } } public void log(String msg) throws InterruptedException { //放入日志队列并阻塞队列 synchronized(this) { if(isShutdown) throw new IllegalStateException("日志开关没有打开"); ++reservations; } queue.put(msg); } public void stop() { synchronized(this) { isShutdown = true; } //中断线程 loggerThread.interrupt(); } private class LoggerThread extends Thread { public void run() { try { while(true) { try { //对日志类上锁 synchronized(LogService.this) { if(isShutdown && reservations == 0) { break;//停止线程 } } //取出日志信息 String msg = queue.take(); //提交成功一条,对阻塞的数据计数减少一条 synchronized(LogService.this) { --reservations; } System.out.println(msg); } catch (InterruptedException e) { e.printStackTrace(); } } } finally { System.out.println("日志结束.........."); } } } @Test public void test() { LogService log = new LogService(); log.start(); int i = 1; while(true) { try { Thread.currentThread().sleep(2000); //把日志放入队列 log.log("这是日志:" + i++); if(i == 3) { log.stop(); } } catch (InterruptedException e) { e.printStackTrace(); } } } }