was控制台无法停止应用

问题描述:

  was控制台无法停止应用,只能通过停止server的方式停止;

代码实现:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.LinkedBlockingQueue;

/**
 * @className MessageReceiver
 * @Desc 消息接收处理
 * @Author HZ
 * @Date 2019/11/25 9:39
 * @Version 1.0
 */
public class MessageReceiver implements Runnable{

    private final static Logger LOGGER = LoggerFactory.getLogger(MessageReceiver.class);

    /**
     * 通信消息队列
     * */
    private LinkedBlockingQueue<String> messageQueue = new LinkedBlockingQueue<>();

    /**
     * 线程名
     * */
    private final static String threadName = "MessageReceiver";

    /**
     * 运行标志
     * */
    private volatile boolean isRunning = true;

    /**
     * 线程
     * */
    private Thread messageQueueThread;

    /**
     * 锁 用作休眠与唤醒
     * */
    private Object lock = new Object();

    /**
     * @title
     * @Description 初始化
     * @Author HZ
     * @Param
     * @Return
     * @Date: 2019/11/25 10:59
     */
    public void init(){
        this.messageQueueThread = new Thread(this, threadName);
        this.messageQueueThread.start();
    }

    /**
     * @title destory
     * @Description 停止时销毁
     *  lock.notifyAll();先唤醒messageQueueThread线程!!!
     *  this.messageQueueThread.join();等待messageQueueThread线程执行完
     * @Author HZ
     * @Param []
     * @Return void
     * @Date: 2019/11/25 10:59
     */
    public void destory(){
        this.isRunning = false;

        synchronized (lock) {
            lock.notifyAll();
            LOGGER.info("强制唤醒messageQueueThread");
        }

        if (this.messageQueueThread != null) {
            try {
                this.messageQueueThread.join();
            } catch (InterruptedException e) {
                LOGGER.info("线程关闭失败...错误信息={}", e);
            }
        }
        LOGGER.info("destroy MessageDatacommReceiver success");
    }

    /**
     * @title pushIntoQueue
     * @Description 把对象放入队列
     * @Author HZ
     * @Param [str]
     * @Return void
     * @Date: 2019/11/25 11:01
     */
    public void pushIntoQueue(String str){
        try {
            synchronized (lock) {
                this.messageQueue.put(str);
                LOGGER.debug("开始唤醒messageQueueThread线程");
                lock.notifyAll();
            }
        } catch (InterruptedException e) {
            LOGGER.error("把对象放入队列...错误信息={}", e);
        }
    }

    /**
     * @title run
     * @Description 线程主方法
     * @Author HZ
     * @Param []
     * @Return void
     * @Date: 2019/11/25 11:01
     */
    @Override
    public void run(){
        while(this.isRunning){
            try {
                synchronized (lock) {
                    if(this.messageQueue.isEmpty()){
                        lock.wait();
                        LOGGER.debug("messageQueueThread线程被唤醒");
                    }else{
                        //TODO 业务方法
                    }
                }
            }catch (Exception e) {
                // 捕获异常,防止线程死掉
                LOGGER.error("messageQueueThread发生未预计的异常", e);
            }
        }
    }
}

功能描述:

  实例化MessageReceiver类时调用init()方法,创建并启动一个线程messageQueueThread

  messageQueueThread线程的停止依靠运行标记isRunning控制

  生产者通过调用pushIntoQueue方法将待处理事件放入到阻塞队列messageQueue, 同时调用notifyAll通知messageQueueThread取获取数据

  messageQueueThread循环从阻塞队列messageQueue中获取数据,没有获取到值则调用wait方法阻塞 MessageReceiver对象销毁时调用destory方法

问题原因:

  destory()中没有调用lock.notifyAll();这段代码

  导致调用this.messageQueueThread.join();方法时messageQueueThread一直阻塞没有执行,该对象也就无法销毁,资源无法释放

        synchronized (lock) {
            lock.notifyAll();
            LOGGER.info("强制唤醒messageQueueThread");
        }

参考文档:

https://www.cnblogs.com/yanze/p/10032363.html

https://blog.csdn.net/jiangguilong2000/article/details/11617529

猜你喜欢

转载自www.cnblogs.com/lyrb/p/11926752.html