题目描述:
模拟一个场景:处理16条日志记录,每条日志记录打印时间须要1秒,正常状况下若是将这16条记录去部打完须要16秒,如今为了提升效率,准备开启4个线程去打印,4秒钟打印完,实现这个demo。ide
先来分析一下这个题目,关于这16条日志记录,咱们能够在主线程中产生出来,这没用什么难度,关键是开启4个线程去执行,如今有两种思路:一种是日志的产生和打印日志的线程在逻辑上分开;一种是日志的产生和打印日志的线程在逻辑上不是分开的。这样说可能有点晦涩,下面我针对这两种思路,写个实现的demo就好理解了。spa
这至关于两条战线: 一条战线在不停的产生日志,另外一个战线在不停的打印日志。很明显会想到阻塞队列的使用,产生日志不停的往阻塞队列中塞,打印日志不停的从阻塞队列中取,阻塞队列的大小能够本身设置,能够设置16个,也能够设置为1个,这都不影响执行。因此会用到BlockingQueue,下面看一下实现的demo:线程
public class QuestionOne { public static void main(String[] args) { //定义一个阻塞队列,队列大小能够装16个信息 BlockingQueue<String> queue = new ArrayBlockingQueue<String>(16); for(int i = 0; i < 4; i ++) { //开启四个线程去阻塞队列中取日志打印 new Thread(new Runnable() { @Override public void run() { while(true) { try { String log = queue.take(); //取日志 parseLog(log); //打印日志 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }).start(); } System.out.println("begin:" + (System.currentTimeMillis()/1000)); for(int i = 0; i < 16; i ++) { final String log = "" + (i+1); //表示一个日志 try { queue.put(log); //将产生的日志塞到阻塞队列中去 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void parseLog(String log) { //打印日志的方法 System.out.println(Thread.currentThread().getName() + "---" + log + "---" + (System.currentTimeMillis()/1000)); try { Thread.sleep(1000); //模拟打印一第二天志须要1秒 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
这就比如一个系统正在运做,一边不停的产生日志,一边在不停的开启多个线程去打印日志信息,这个demo就写好了,运行结果就不贴了。日志
public class QuestionOnePool { public static void main(String[] args) { ExecutorService service = Executors.newFixedThreadPool(4);//建立一个线程池 System.out.println("begin:" + (System.currentTimeMillis()/1000)); for(int i = 0; i < 16; i ++) { final String log = "" + (i+1); //表示一个日志 service.execute(new Runnable() { //拿一个线程去执行 @Override public void run() { parseLog(log); } }); } service.shutdown(); //最后别忘了关掉线程池 } public static void parseLog(String log) { System.out.println(Thread.currentThread().getName() + "--开始打印-" + log + "---" + (System.currentTimeMillis()/1000)); try { Thread.sleep(1000); //模拟打印一第二天志须要1秒 System.out.println(Thread.currentThread().getName() + "--结束打印-" + log + "---" + (System.currentTimeMillis()/1000)); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }