首页 > 技术文章 > 【JAVA并发编程实战】7、日志服务

cutter-point 2016-11-08 10:48 原文

这里是一个应用项目使用生产消费模型的日志类

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();
            }
        }
    }
}

 

推荐阅读