线程池的使用和原理

线程池的使用和原理

目录

一、线程池的作用

二、线程池的关系图

三、线程池的创建及参数

四、线程池的使用原理

五、线程池的使用

 

一、线程池的作用

随着cpu核数越来越多,不可避免的利用多线程技术以充分利用其计算能力。所以,多线程技术是服务端开发人员必须掌握的技术。线程的创建和销毁,都涉及到系统调用,比较消耗系统资源,所以就引入了线程池技术,线程池中有已经创建好的线程,可直接使用,并且使用完了,直接再次放回线程池,避免频繁的线程创建和销毁。

 

二、线程池的关键类的关系图

线程池的使用和原理

 

从上面可以看出Java的线程池主的实现类主要有两个类ThreadPoolExecutor和ForkJoinPool。

ForkJoinPool是Fork/Join框架下使用的一个线程池,一般情况下,我们使用的比较多的就是ThreadPoolExecutor。我们大多数时候创建线程池是通过Executors

三、线程池的创建和参数解析

先看一个参数最完整的创建线程池的构造方法

线程池的使用和原理

参数解析:

corePoolSize:线程池的核心线程数,说白了就是,即便是线程池里没有任何任务,也会有corePoolSize个线程在候着等任务。

maximumPoolSize:最大线程数,不管你提交多少任务,线程池里最多工作线程数就是maximumPoolSize。

keepAliveTime:线程的存活时间。当线程池里的线程数大于corePoolSize时,如果等了keepAliveTime时长还没有任务可执行,则线程退出。

unit:这个用来指定keepAliveTime的单位,比如秒:TimeUnit.SECONDS。

workQueue:一个阻塞队列,提交的任务将会被放到这个队列里。

threadFactory:线程工厂,用来创建线程,主要是为了给线程起名字,默认工厂的线程名字:pool-1-thread-3。

handler:拒绝策略,当线程池里线程被耗尽,且队列也满了的时候会调用。

 

线程池创建:

java.util.concurrent.Executosr是线程池的静态工厂,我们通常使用它方便地生产各种类型的线程池,主要的方法有四种:

1、newSingleThreadExecutor()——创建一个单线程的线程池

2、newFixedThreadPool(int n)——创建一个固定大小的线程池

3、newCachedThreadPool()——创建一个可缓存的线程池

4、newScheduledThreadPool()——创建一个固定线程数的线程池,支持定时及周期性执行后台任务。

 

(1)newSingleThreadExecutor()单线程数的线程池

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}

public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>(),
                                threadFactory));

最关键的是corePoolSize(核心线程数)参数和maximumPoolSize(最大线程数)两个参数都是1

(2)newFixedThreadPool()固定线程数的线程池

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>(),
                                  threadFactory);

可以看出corePoolSize(核心线程数)参数和maximumPoolSize(最大线程数)两个参数都是相等

(3)newCachedThreadPool()创建一个可以根据需要创建新线程的线程池,它是没有线程数量限制的

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>(),
                                  threadFactory);
}

corePoolSize=0,maximumPoolSize=Integer.MAX_VALUE(认为是无限大)keepAliveTime=60s,当60s秒后没有任务执行的线程将会退出,由于CachedThreadPool线程没有上线,无线创建线程需要大量的内存,需要谨慎使用

(4)newScheduledThreadPool():创建一个固定线程数的线程池,支持定时及周期性执行后台任务。这个用的比较少,就略过

四、线程池的运行原理

用一张图来描述线程池执行的流程

线程池的使用和原理

该图对应如下源码:

线程池的使用和原理

五、线程池使用

实例

(1)newSingleThreadExecutor

MyThread.java

public class MyThread extends Thread{
	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println(Thread.currentThread().getName() + "正在执行。。。");
	}
}

ThreadPoolTest.java

ThreadPoolTest.java
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolTest {

	public static void main(String[] args) {
        //创建一个可重用固定线程数的线程池
        ExecutorService pool = Executors. newSingleThreadExecutor();
        //创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口
        Thread t1 = new MyThread();
        Thread t2 = new MyThread();
        Thread t3 = new MyThread();
        Thread t4 = new MyThread();
        Thread t5 = new MyThread();
        //将线程放入池中进行执行
        pool.execute(t1);
        pool.execute(t2);
        pool.execute(t3);
        pool.execute(t4);
        pool.execute(t5);
        //关闭线程池
        pool.shutdown();
    }
}

运行结果:

线程池的使用和原理

(2)newFixedThreadPool

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolTest {

	public static void main(String[] args) {
        //创建一个可重用固定线程数的线程池
        //ExecutorService pool = Executors. newSingleThreadExecutor();
        //固定线程池大小
        ExecutorService pool = Executors.newFixedThreadPool(2);
        //创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口
        Thread t1 = new MyThread();
        Thread t2 = new MyThread();
        Thread t3 = new MyThread();
        Thread t4 = new MyThread();
        Thread t5 = new MyThread();
        //将线程放入池中进行执行
        pool.execute(t1);
        pool.execute(t2);
        pool.execute(t3);
        pool.execute(t4);
        pool.execute(t5);
        //关闭线程池
        pool.shutdown();
    }
}

运行结果:

线程池的使用和原理

(3)newCachedThreadPool

根据上面一样,只修改一句话

//创建一个可重用固定线程数的线程池

ExecutorService pool = Executors.newCachedThreadPool();

运行结果:

线程池的使用和原理

好了,线程池的简单介绍先到这里,如有不对,请多多指教。

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/111249.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • smartctl

    smartctl安装和开启服务检查硬盘是否开启smartctl(最后两行)

    2022年6月15日
    44
  • 机器学习之K均值聚类

    K均值聚类思想  聚类的核心概念是相似度或距离,有很多相似度或距离的方法,比如欧式距离、马氏距离、相关系数、余弦定理、层次聚类和K均值聚类等  K均值聚类的

    2021年12月30日
    35
  • c语言gdi绘图_程序设计的基本步骤是

    c语言gdi绘图_程序设计的基本步骤是本文将实现对基本图形的绘制:windows程序画图,大体上有3种方法:(1)你告诉系统点的坐标和颜色,系统通过SetPixel来画。类似的,通过GetPixel来获取某一点像素值。(2)使用MoveToEx、LineTo来划线,MoveToEx设置起点坐标,LineTo设置终点坐标,或者使用Polyline函数,这个函数接受一个POINT类型的数组,通过数组里的点连线。(3)windows…

    2022年8月18日
    5
  • vmware15最新激活码2021(注册激活)[通俗易懂]

    (vmware15最新激活码2021)最近有小伙伴私信我,问我这边有没有免费的intellijIdea的激活码,然后我将全栈君台教程分享给他了。激活成功之后他一直表示感谢,哈哈~https://javaforall.net/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~MLZP…

    2022年3月20日
    208
  • UNIX基本操作命令

    UNIX基本操作命令UNIX命令基础登录系统:输入密码,密码不显示退出系统:ctrl+dexitlogout创建/修改密码:passwd密码输入后不显示,新密码要输入两次,匹配成功才算是修改密码成功UNIX命令格式:命令选项参数快捷键:ctrl+c:中断当前命令执行并返回shellctrl+d:终端传输或结束文本编辑ctrl+s:临时中断命令的屏幕输出ctrl+q:恢复由ctrl+s的临时中断ctrl+u:清除输入的整个命令行backspace:删除某个错误输入的字符常用操作命令

    2022年5月31日
    433
  • zoj1942

    zoj1942一开始连题目都没看都就乱写以为是要输出最短路径然后还理解了很久所要输出的距离所走路径的最小边当有直达的边时,如果比其他路线的最大边要小,那就是这个直达边如果比其他路线的最大边要大,那就输出其他路线的最大边的最小边说起来好像很绕。。自己的理解能力还是太差了#include#include#includeusingnamespacestd;double

    2022年7月12日
    23

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号