博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
线程池概念
阅读量:3950 次
发布时间:2019-05-24

本文共 3609 字,大约阅读时间需要 12 分钟。

线程池概念

  线程池可以简单的看作是一个“容器”,当我们的程序在第一次启动的时候,就创建多个线程,放到这个容器中,在需要使用线程来执行某个任务的时候,就直接到这个容器中来取一个线程使用,当该任务执行完毕之后,再将此线程回收到容器中,等待下一个被执行的任务来使用。

一、线程池出现的背景

  以前我们程序中要执行一个任务,需要先new一个线程用来执行这个任务,执行完之后,这个线程也就被销毁了,如果此时又有一个新的任务需要被执行,那么我们只能继续new一个线程,创建……销毁……创建……销毁……,反复如此,给我们的系统带来了巨大的开销,性能大打折扣。

  在JDK1.5版本之后,java内置了线程池,我们可以直接使用。线程池中的线程到底是如何与任务进行交互的呢?
  在下面图中,线程池中我们预先创建了4个线程,每个任务在执行的时候都将会使用一个线程,到task05任务的时候发现线程池中的4个线程都被前面的4个任务使用了,那么此时他就会在任务队列中等待,当前面的4个任务执行完毕之后,会将线程回收到线程池中,此时task05任务就可以从线程池中获取一个线程来执行相应的任务了。
在这里插入图片描述

二、使用线程池的好处

  1. 有效的节约了资源,每条线程都可以重复使用,不必再重复取创建和销毁,提升了系统的性能。
  2. 提高了响应的速度,因为线程的创建和销毁都会消耗一定的时间,有了线程池之后,需要使用线程直接到池子中拿一根就行了。
  3. 使用线程池可以统一管理线程。

三、创建线程池

  在java.util.concurrent包(也就是常说得J.U.C)中,提供了一个创建线程池得工厂类:Executors。通过该类中的newFixedThreadPool()方法可以创建一个拥有指定数量线程的线程池。

public class RunnableImpl implements Runnable {
@Override public void run() {
//设置线程任务 System.out.println("这里是需要线程执行的任务代码"); }}
public class test03 {
public static void main(String[] args) {
//创建线程数为2的一个线程池 ExecutorService executorService = Executors.newFixedThreadPool(2); //提交需要执行的任务 executorService.submit(new RunnableImpl()); //关闭线程池(注意:关闭线程池之后,线程也就不存在了,如果在关闭线程池之后又提交了需要执行的任务将会报错) executorService.shutdown(); }}

  通过上面的方式,我们可以从线程池中获取线程并执行被提交的任务,如果你使用了阿里规约插件Alibaba java Coding Guidelines,那么使用上面这种方式可能会给你提示建议使用 ThreadPoolExecutor类来创建线程,那么使用这种方式该如何创建呢?

  1. 查看ThreadPoolExecutor类的源码
    new ThreadPoolExecutor对象的时候,大家可以看到提示参数如下:
public ThreadPoolExecutor(int corePoolSize,                              int maximumPoolSize,                              long keepAliveTime,                              TimeUnit unit,                              BlockingQueue
workQueue) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); }
- corePoolSize:核心线程数

  默认情况下,创建一个线程池之后,线程池中的线程数为0,当有任务来了,就会创建一个线程去执行任务,当线程池中的线程数量达到corePoolSize,就会把到达的任务放到任务队列 workQueue中。

  当线程数小于corePoolSize的时候,来了任务线程池也会优先去创建新的线程来执行新任务
  如果没有设置allowCoreThreadTimeOut(true),则线程池中的线程数最少应该保持在corePoolSize的数量。

- maximumPoolSize:线程池中最多能够创建的线程数量。
- keepAliveTime:线程在没有任务的情况下,最多能够存活的时间。

  默认的情况下,当线程池中的线程数量大于corePoolSize的时候,该时间才会生效,也就是说:当线程数量 > corePoolSize的时候,如果线程的空闲时间达到了keepAliveTime,则该线程会被终止,如果该参数设置为0,则线程执行完毕之后会被立即回收。直到线程池的线程数量不大于corePoolSize为止。

  如果调用了allowCoreThreadTimeOut方法,在线程池中的线程数量不大于corePoolSize的时候,keepAliveTime参数也会生效,直到线程池中的线程数量为0为止。

-TimeUnit时间单位
- BlockingQueue任务队列

  当线程池中没有空闲的线程去执行任务的时候,该任务就会被存放到此队列中。

  如果任务队列已满,又有新的任务进来的时候,将会在非corePool中创建新的的线程去处理任务,也就是说:队列未满之前,所有的任务都将在任务队列中阻塞等待被执行,而不是新建一个非corePool中的线程去执行任务。

线程池执行原理流程图

使用ThreadPoolExecutor创建线程池

public class RunnableImpl implements Runnable {	@Override	public void run() {		//设置线程任务		System.out.println(Thread.currentThread().getName() + "这里是需要线程执行的任务代码");	}}
public class test03 {	public static void main(String[] args) {		//创建线程数为2的一个线程池//		ExecutorService executorService = Executors.newFixedThreadPool(2);		ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 500, TimeUnit.MILLISECONDS, new ArrayBlockingQueue
(5)); //提交需要执行的任务 for (int i = 0; i < 11; i++) { threadPoolExecutor.execute(new RunnableImpl()); } //关闭线程池(注意:关闭线程池之后,线程也就不存在了,如果在关闭线程池之后又提交了需要执行的任务将会报错) threadPoolExecutor.shutdown(); }}

运行main方法:

pool-1-thread-1这里是需要线程执行的任务代码pool-1-thread-1这里是需要线程执行的任务代码pool-1-thread-1这里是需要线程执行的任务代码pool-1-thread-1这里是需要线程执行的任务代码pool-1-thread-1这里是需要线程执行的任务代码pool-1-thread-1这里是需要线程执行的任务代码pool-1-thread-2这里是需要线程执行的任务代码pool-1-thread-3这里是需要线程执行的任务代码pool-1-thread-4这里是需要线程执行的任务代码pool-1-thread-5这里是需要线程执行的任务代码

  因为corePoolSize设置为5,所以最多只能同时有5个线程去执行。

  上面的流程图中,我们知道线程太多的话,线程池可能会拒绝处理任务,那在线程池中,究竟有哪些拒绝策略呢?下一篇文章专门记录。

转载地址:http://hjhwi.baihongyu.com/

你可能感兴趣的文章
python的collections
查看>>
J2ME程序开发新手入门九大要点
查看>>
双向搜索算法
查看>>
日本GAME製作方式
查看>>
移动行业术语资料
查看>>
3G到来将全面颠覆SP、CP游戏规则
查看>>
射击游戏中跟踪弹及小角度移动的开发
查看>>
播放声音文件的完整源代码
查看>>
J2ME编程最佳实践之灵活的RMS应用
查看>>
MOBILE FIRST: HOW TO APPROACH MOBILE WEBSITE TESTING? 移动优先:如何处理移动网站测试?
查看>>
开始使用Retrofit 2 HTTP 客户端
查看>>
对于初学者练习的6个开源项目
查看>>
保持冷静和需要打破的东西:软件测试初学者
查看>>
如何通过连接您的业务应用程序来节省时间
查看>>
熟悉现代JavaScript的培训计划
查看>>
7本书从小工到数据分析专家
查看>>
程序设计的基本原则:栈和堆
查看>>
Android应用程序架构
查看>>
Android:绘制自定义视图
查看>>
Android开发:一些有用的库(第一部分)
查看>>