线程池(ThreadPoolExecutor ) 的关闭与监控

https://blog.csdn.net/wangmx1993328/article/details/80648238

参考文章:《线程池理论 之 线程池饱和策略 与 工作队列排队策略》、《线程池(ThreadPoolExecutor) 创建与使用》


关闭线程池

可以通过调用线程池的shutdown或shutdownNow方法来关闭线程池。
原理都是遍历线程池中的工作线程,然后逐个调用线程的interrupt方法来中断线程,所以无法响应中断的任务可能永远无法终止。
只要调用了这两个关闭方法中的任意一个,isShutdown方法就会返回true。
当所有的任务都已关闭后,才表示线程池关闭成功,这时调用isTerminaed方法会返回true。
至于应该调用哪一种方法来关闭线程池,应该由提交到线程池的任务特性决定,通常调用shutdown方法来关闭线程池,如果任务不一定要执行完,则可以调用shutdownNow方法。
实际项目中线程池需要关闭的情况还是较少的,就像数据库连接池打开之后不会去关闭一样。
线程池中的线程执行任务,Runnable的run方法执行完了,表示任务执行完了,线程也就不再是活动状态了。

shutdown

public void shutdown():按过去执行已提交任务的顺序发起一个有序的关闭
之前提交的任务会被执行(包含正在执行的,工作队列中的),但新任务会被拒绝
如果已经关闭,则调用没有任何作用。

shutdownNow

public List<Runnable> shutdownNow():尝试停止所有活动的正在执行的任务,停止等待任务的处理,并返回正在等待被执行的任务列表
shutdownNow会强制停止所有正在执行的任务
监控线程池
如果在系统中大量使用线程池,则有必要对线程池进行监控,方便在出现问题时,可以根据线程池的使用状况快速定位问题。
可以通过线程池提供的参数进行监控,在监控线程池的时候可以使用以下属性


1、taskCount:线程池需要执行的任务数量,是个近似值。
2、completedTaskCount:线程池在运行过程中已完成的任务数量,小于或等于taskCount,是个近似值。
3、largestPoolSize:线程池里曾经创建过的最大线程数量。通过这个数据可以知道线程池是否曾经满过。如该数值等于线程池的最大大小,则表示线程池曾经满过。
4、poolSize:线程池当前的线程数总量,包括活动的线程与闲置的线程。
5、activeCount:获取活动的线程数。
 

boolean isTerminated()
若关闭后所有任务都已完成,则返回true。注意除非首先调用shutdown或shutdownNow,否则isTerminated永不为true。返回:若关闭后所有任务都已完成,则返回true。

/**
 * Created by Administrator on 2018/6/8 0008.
 * 线程池任务执行类
 */
public class ThreadPoolTask implements Runnable, Serializable {
    /**
     * threadPoolTaskData:模拟调用线程传入的数据
     * threadPool:为了统计信息而传入进来的
     */
    private Integer threadPoolTaskData;
    private ThreadPoolExecutor threadPool;
 
    ThreadPoolTask(Integer tasks, ThreadPoolExecutor threadPool) {
        this.threadPoolTaskData = tasks;
        this.threadPool = threadPool;
    }
 
    public void run() {
        System.out.println("------------------------------");
        System.out.println("曾计划执行的近似任务总数:"+threadPool.getTaskCount());
        System.out.println("已完成执行的近似任务总数:"+threadPool.getCompletedTaskCount());
        System.out.println("池中曾出现过的最大线程数:"+threadPool.getLargestPoolSize());
        System.out.println("返回线程池中的当前线程数:"+threadPool.getPoolSize());
        System.out.println("线程池中的当前活动线程数:"+threadPool.getActiveCount());
        System.out.println("线程池中约定的核心线程数:"+threadPool.getCorePoolSize());
        System.out.println("线程池中约定的最大线程数:"+threadPool.getMaximumPoolSize());
        for (int i = 0; i < 2; i++) {
            System.out.println("--------线程名:" + Thread.currentThread().getName() + ":" + (threadPoolTaskData++));
            try {
                /**用延时来模拟线程在操作*/
                Thread.sleep(2000);
            } catch (Exception e) {
                System.out.println("支线程异常:"+e.getMessage());
                e.printStackTrace();
            }
        }
    }
}

/**
 * Created by Administrator on 2018/6/8 0008.
 * 线程池测试类
 */
public class ThreadPoolExecutorTest {
    public static void main(String[] args) {
        /** 构造器方式构造线程池*/
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 3,
                60, TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(1),
                new ThreadPoolExecutor.DiscardOldestPolicy());
 
        /**循环产生多个任务,并将其加入到线程池去执行*/
        for (int i = 0; i < 5; i++) {
            try {
                threadPool.execute(new ThreadPoolTask(1, threadPool));
                /**便于观察,延时*/
                Thread.sleep(1000);
            } catch (Exception e) {
                System.out.println("异常:" + e.getMessage());
                e.printStackTrace();
            }
        }
        System.out.println("主线程开始检测线程池活动线程个数...");
        /**总共检测20秒,每隔2秒检测一次
         * 当活动线程为0(即任务执行完毕)时,关闭线程池*/
        for (int i = 0; i < 10; i++) {
            System.out.println("主线程判断池中正活动线程数:" + threadPool.getActiveCount());
            System.out.println("主线程判断池中已完成线程数:" + threadPool.getCompletedTaskCount());
            if (threadPool.getActiveCount() <= 0) {
                threadPool.shutdown();
                break;
            }
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        /** 如果上面循环检测没有关闭线程池,则最后强制关闭一次*/
        if (!threadPool.isTerminated()) {
            System.out.println("强制关闭线程池....");
            threadPool.shutdownNow();
        }
    }
}


--------------结果输出---------------------

------------------------------
曾计划执行的近似任务总数:1
已完成执行的近似任务总数:0
池中曾出现过的最大线程数:1
返回线程池中的当前线程数:1
线程池中的当前活动线程数:1
线程池中约定的核心线程数:2
线程池中约定的最大线程数:3
--------线程名:pool-1-thread-1:1
------------------------------
曾计划执行的近似任务总数:2
已完成执行的近似任务总数:0
池中曾出现过的最大线程数:2
返回线程池中的当前线程数:2
线程池中的当前活动线程数:2
线程池中约定的核心线程数:2
线程池中约定的最大线程数:3
--------线程名:pool-1-thread-2:1
--------线程名:pool-1-thread-1:2
--------线程名:pool-1-thread-2:2
------------------------------
曾计划执行的近似任务总数:4
已完成执行的近似任务总数:0
池中曾出现过的最大线程数:3
返回线程池中的当前线程数:3
线程池中的当前活动线程数:3
线程池中约定的核心线程数:2
线程池中约定的最大线程数:3
--------线程名:pool-1-thread-3:1
------------------------------
曾计划执行的近似任务总数:4
已完成执行的近似任务总数:1
池中曾出现过的最大线程数:3
返回线程池中的当前线程数:3
线程池中的当前活动线程数:3
线程池中约定的核心线程数:2
线程池中约定的最大线程数:3
--------线程名:pool-1-thread-1:1
--------线程名:pool-1-thread-3:2
主线程开始检测线程池活动线程个数...
主线程判断池中正活动线程数:2
主线程判断池中已完成线程数:2
--------线程名:pool-1-thread-1:2
主线程判断池中正活动线程数:1
主线程判断池中已完成线程数:3
主线程判断池中正活动线程数:0
主线程判断池中已完成线程数:4
Process finished with exit code 0

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值