我的编程空间,编程开发者的网络收藏夹
学习永远不晚

怎么在Java中使用线程工厂监控线程池

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

怎么在Java中使用线程工厂监控线程池

这期内容当中小编将会给大家带来有关怎么在Java中使用线程工厂监控线程池,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

ThreadFactory

线程池中的线程从哪里来呢?就是ThreadFoctory

public interface ThreadFactory {    Thread newThread(Runnable r);}

Threadfactory里面有个接口,当线程池中需要创建线程就会调用该方法,也可以自定义线程工厂

public class ThreadfactoryText {    public static void main(String[] args) {        Runnable runnable=new Runnable() {            @Override            public void run() {                int num=new Random().nextInt(10);                System.out.println(Thread.currentThread().getId()+"--"+System.currentTimeMillis()+"--睡眠"+num);                try {                    TimeUnit.SECONDS.sleep(num);                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        };        //创建线程池 使用自定义线程工厂 采用默认的拒绝策略        ExecutorService executorService=new ThreadPoolExecutor(5, 5, 0, TimeUnit.SECONDS, new SynchronousQueue<>(), new ThreadFactory() {            @Override            public Thread newThread(Runnable r) {                Thread t=new Thread(r);                t.setDaemon(true);//设置为守护线程,当主线程运行结束,线程池中线程也会被释放                System.out.println("创建了线程"+t);                return t;            }        });        //提交五个任务        for (int i = 0; i < 5; i++) {            executorService.submit(runnable);        }    }}

怎么在Java中使用线程工厂监控线程池

当线程提交超过五个任务时,线程池会默认抛出异常

监控线程池

ThreadPoolExcutor提供了一组方法用于监控线程池

int getActiveCount()//获得线程池只当前的获得线程数量long getCompletedTaskCount()//返回线程池完成任务数量int getCorePoolSize()//线程池中核心任务数量int getLargestPoolSize() //返回线程池中曾经达到线程的最大数int getMaximumPoolSize()//返回线程池的最大容量int getPoolSize()//返回线程大小BlockingQueue<Runnable> getQueue()//返回阻塞队列long getTaskCount()//返回线程池收到任务总数
public class Text {    public static void main(String[] args) throws InterruptedException {        Runnable runnable = new Runnable() {            @Override            public void run() {                System.out.println(Thread.currentThread().getId() + "线程开始执行--" + System.currentTimeMillis());                try {                    Thread.sleep(10000);                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        };        //创建线程池 使用默认线程工厂 有界队列  采用DiscardPolicy策略        ThreadPoolExecutor executorService = new ThreadPoolExecutor(2, 5, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5),Executors.defaultThreadFactory(),new ThreadPoolExecutor.DiscardPolicy());        //提交五个任务        for (int i = 0; i < 30; i++) {            executorService.submit(runnable);            System.out.println("当前线程核心线程数"+executorService.getCorePoolSize()+",最大线程数:"+executorService.getMaximumPoolSize()+",当前线程池大小:"+executorService.getPoolSize()+"活动线程数:"+executorService.getActiveCount()+",收到任务:"+executorService.getTaskCount()+"完成任务数:"+executorService.getCompletedTaskCount()+"等待任务数:"+executorService.getQueue().size());            TimeUnit.MILLISECONDS.sleep(500);        }        System.out.println("-------------------");        while (executorService.getActiveCount()>=0)//继续对线程池进行检测        {          System.out.println("当前线程核心线程数"+executorService.getCorePoolSize()+",最大线程数:"+executorService.getMaximumPoolSize()+",当前线程池大小:"+executorService.getPoolSize()+"活动线程数:"+executorService.getActiveCount()+",收到任务:"+executorService.getTaskCount()+"完成任务数:"+executorService.getCompletedTaskCount()+"等待任务数:"+executorService.getQueue().size());            Thread.sleep(1000);//每1秒检测一次        }    }}

当线程池大小达到了核心线程数,线程会被放在等待队列。当线程池等待队列已满会开启新的线程。当当前线程大小达到最大线程数,等待队列也满了,再提交的话会执行DiscardPolicy策略,直接丢弃这个无法处理的任务,最后30个任务只剩下15个了。

怎么在Java中使用线程工厂监控线程池

原理如图:

怎么在Java中使用线程工厂监控线程池

扩展线程池

有时候需要对线程池进行扩展,如在监控每个任务开始和结束时间,或者自定义其他增强功能。

ThreadPoolExecutor线程池提供了两个方法:

protected void beforeExecute(Thread t, Runnable r) { }protected void afterExecute(Runnable r, Throwable t) { }

线程池执行某个任务前会执行beforeExecute()方法,执行后会调用afterExecute()方法

查看ThreadPoolExecutor源码,在该类中定义了一个内部类Worker,ThreadPoolExecutor线程池的工作线程就是Worker类的实例,Worker实例在执行时会调用beforeExecute与afterExecute方法。

public void run() {            runWorker(this);}final void runWorker(Worker w) {                try {                    beforeExecute(wt, task);                    try {                        task.run();                        afterExecute(task, null);                    } catch (Throwable ex) {                        afterExecute(task, ex);                        throw ex;                    }                } finally {                    task = null;                    w.completedTasks++;                    w.unlock();                }            }    }

部分代码已省略,线程执行前会调用beforeExecute,执行后会调用afterExecute方法。

扩展线程池示例

package com;import java.util.concurrent.ExecutorService;import java.util.concurrent.LinkedBlockingDeque;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;public class Text07 {    public static void main(String[] args) {        //定义扩展线程池 定义线程池类继承ThreadPoolExecutor,然后重写其他方法        ExecutorService threadPoolExecutor= new ThreadPoolExecutor(5,5,0, TimeUnit.SECONDS,new LinkedBlockingDeque<>()){     //在内部类重写开始方法     @Override     protected void beforeExecute(Thread t, Runnable r) {         System.out.println(t.getId()+"线程准备执行任务"+((Mytask)r).name);     }     //在内部类重写结束方法     @Override     protected void afterExecute(Runnable r, Throwable t) {         System.out.println(((Mytask)r).name+"执行完成");     }     //线程池退出     @Override     protected void terminated() {         System.out.println("线程池退出");     } };        for (int i = 0; i < 5; i++) {            Mytask mytask=new Mytask("Thread"+i);            threadPoolExecutor.execute(mytask);        }    }    private  static  class  Mytask implements Runnable    {        private  String name;        public  Mytask(String name)        {            this.name=name;        }        @Override        public void run() {            System.out.println(name+"正在被执行"+Thread.currentThread().getId());            try {                Thread.sleep(1000);//模拟任务时长            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}

怎么在Java中使用线程工厂监控线程池

优化线程池大小

线程池大小对系统性能有一定影响,过大或者过小都无法方法发挥系统最佳性能,不需要非常精确,只要避免极大或者极小就可以了,一般来说线程池大小大姚考虑CPU数量

线程池大小=CPU数量 * 目标CPU使用率*(1+等待时间与计算时间的比)

线程池死锁

如果线程池执行中,任务A在执行过程中提交了任务B,任务B添加到线程池中的等待队列,如果A的结束需要B的执行结果,而B线程需要等待A线程执行完毕,就可能会使其他所有工作线程都处于等待状态,待这些任务在阻塞队列中执行。线程池中没有可以对阻塞队列进行处理的线程,就会一直等待下去照成死锁。

适合给线程池提交相互独立的任务,而不是彼此依赖的任务,对于彼此依赖的任务,可以考虑分别提交给不同的线程池来处理。

线程池异常信息捕获

import java.util.concurrent.ExecutorService;import java.util.concurrent.SynchronousQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;public class Text09 {    public static void main(String[] args) {        //创建线程池        ExecutorService executorService=new ThreadPoolExecutor(5,5,0, TimeUnit.SECONDS,new SynchronousQueue<>());        //向线程池中添加两个数相处计算的任务        for (int i = 0; i <5 ; i++) {            executorService.submit(new Text(10,i));        }    }    private  static class  Text implements  Runnable    {        private  int x;        private  int y;        public  Text(int x,int y)        {            this.x=x;            this.y=y;        }        @Override        public void run() {            System.out.println(Thread.currentThread().getName()+"线程x/y结果的为"+x+"/"+y+"="+(x/y));        }    }}

怎么在Java中使用线程工厂监控线程池

可以看到只有四条结果,实际向线程池提交了五个任务,但是当i==0时,产生了算术异常,线程池把该异常吃掉了,导致我们对该异常一无所知

解决办法:

把submit改为execute

怎么在Java中使用线程工厂监控线程池

对线程池进行扩展,对submit进行包装

package com;import java.util.concurrent.*;public class Text09 {    public static void main(String[] args) {        //创建线程池  使用自定义的线程池        ExecutorService executorService=new TranceThreadPoorExcuter(5,5,0, TimeUnit.SECONDS,new SynchronousQueue<>());        //向线程池中添加两个数相处计算的任务        for (int i = 0; i <5 ; i++) {            executorService.submit(new Text(10,i));        }    }    public  static class  Text implements  Runnable    {        public  int x;        public  int y;        public  Text(int x,int y)        {            this.x=x;            this.y=y;        }        @Override        public void run() {            System.out.println(Thread.currentThread().getName()+"线程x/y结果的为"+x+"/"+y+"="+(x/y));        }    }    //自定义线程池类 对TranceThreadPoorExcuter进行扩展    private  static  class  TranceThreadPoorExcuter extends  ThreadPoolExecutor    {        public TranceThreadPoorExcuter(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {            super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);        }        //定义一个方法用于传入两个参数 第一个是要接受的任务 第二个是Exception        public  Runnable warp(Runnable r,Exception e)        {            return new Runnable() {                @Override                public void run() {                    try {                        r.run();                    }                    catch (Exception e1)                    {                        e.printStackTrace();                        throw e1;                    }                }            };        }        //重写submit方法        @Override        public Future<?> submit(Runnable task) {            return super.submit(warp(task,new Exception("客户跟踪异常")));        }        //还可以重写excute方法    }}

怎么在Java中使用线程工厂监控线程池

上述就是小编为大家分享的怎么在Java中使用线程工厂监控线程池了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注编程网行业资讯频道。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

怎么在Java中使用线程工厂监控线程池

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

怎么在Java中使用线程工厂监控线程池

这期内容当中小编将会给大家带来有关怎么在Java中使用线程工厂监控线程池,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。ThreadFactory线程池中的线程从哪里来呢?就是ThreadFoctorypu
2023-06-14

SpringBoot线程池和Java线程池怎么使用

这篇文章主要介绍“SpringBoot线程池和Java线程池怎么使用”,在日常操作中,相信很多人在SpringBoot线程池和Java线程池怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”SpringB
2023-07-06

JAVA怎么控制线程池的线程数量

Java中可以通过使用`ThreadPoolExecutor`类来控制线程池的线程数量。`ThreadPoolExecutor`提供了一些方法来设置线程池的属性,例如核心线程数量、最大线程数量、线程空闲时间等。下面是一个示例代码:```ja
2023-10-11

怎么在Android中使用线程池

本篇文章为大家展示了怎么在Android中使用线程池,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。1 、newCachedThreadPool这种线程池比较灵活,也就是说它的池里的线程数量并不是固定
2023-05-30

java怎么使用线程池启动多线程

在 Java 中,可以使用线程池来启动多线程。以下是使用线程池启动多线程的示例代码:首先,需要导入 `java.util.concurrent.ExecutorService` 和 `java.util.concurrent.Executo
2023-09-15

怎么使用Spring开发和监控线程池服务

这篇文章主要介绍“怎么使用Spring开发和监控线程池服务”,在日常操作中,相信很多人在怎么使用Spring开发和监控线程池服务问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么使用Spring开发和监控线程
2023-06-17

怎么在java中关闭线程池

本篇文章为大家展示了怎么在java中关闭线程池,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Java可以用来干什么Java主要应用于:1. web开发;2. Android开发;3. 客户端开发;4
2023-06-14

java怎么停止线程池中的线程

要停止线程池中的线程,可以使用 `ExecutorService` 接口提供的 `shutdown()` 方法来停止线程池。这个方法会平滑地关闭线程池,即等待所有已提交的任务执行完毕后关闭线程池。示例代码如下:```ExecutorServ
2023-08-20

怎么在Java并发包中使用ThreadPoolExecutor线程池

这篇文章给大家介绍怎么在Java并发包中使用ThreadPoolExecutor线程池,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。一、线程池简介线程池的使用主要是解决两个问题:①当执行大量异步任务的时候线程池能够提供
2023-06-15

Java线程池怎么用

小编给大家分享一下Java线程池怎么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、什么是线程池?线程池是一种用于实现计算机程序并发执行的软件设计模式。线程池
2023-06-15

Java线程池是怎么工作的

本篇内容介绍了“Java线程池是怎么工作的”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!线程池的工作原理首先我们看下当一个新的任务提交到线程
2023-06-27

怎么在Java中自定义线程池

这篇文章给大家介绍怎么在Java中自定义线程池,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。【1】接口定义public interface IThreadPool { /**
2023-06-06

怎么在java中使用ThreadPoolExecutor创建一个线程池

这篇文章给大家介绍怎么在java中使用ThreadPoolExecutor创建一个线程池,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Java可以用来干什么Java主要应用于:1. web开发;2. Android开发
2023-06-14

线程池如何在Java项目中使用

今天就跟大家聊聊有关线程池如何在Java项目中使用,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Java通过Executors提供四种线程池,分别为:newCachedThreadP
2023-05-31

怎么对Java 线程池的运行状态进行监控

怎么对Java 线程池的运行状态进行监控?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。总线程数 = 排队线程数 + 活动线程数 + 执行完成的线程数下面给出一个线程池使用示
2023-06-06

Java线程池中多余的线程怎么回收

这篇文章给大家分享的是有关Java线程池中多余的线程怎么回收的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。那么,就以JDK1.8为例分析吧。1.runWorker(Worker w)工作线程启动后,就进入runW
2023-06-15

Java并发之怎么使用线程池

这篇文章主要介绍“Java并发之怎么使用线程池”,在日常操作中,相信很多人在Java并发之怎么使用线程池问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java并发之怎么使用线程池”的疑惑有所帮助!接下来,请跟
2023-06-16

Java线程池怎么使用AbortPolicy策略

本篇内容介绍了“Java线程池怎么使用AbortPolicy策略”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!线程池ThreadPoolEx
2023-07-02

java线程池ThreadPoolExecutor类怎么用

这篇文章将为大家详细讲解有关java线程池ThreadPoolExecutor类怎么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。在《阿里巴巴java开发手册》中指出了线程资源必须通过线程池提供,不允许
2023-06-29

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录