一、整体认识
一般的理解就是,当我们需要执行不同任务的时候,针对每一个任务都需要去独立创建一个线程。这样带来的一个问题就是,频繁地创建和销毁线程需要时间,很消耗资源。为了解决这个问题,Java线程池出现了,那么什么是线程池呢?
预先准备好若干个线程等待着执行任务,当任务来了,就从准备好的线程中拿一个线程来执行我们的任务(这里存放线程的容器,我们叫做线程池)。
线程池带来的好处是:在有大量需要执行的任务情况下,节约资源,避免频繁地创建和销毁线程带来的资源消耗。
二、实现线程池的核心类ThreadPoolExecutor
在Java中,实现线程池的核心类是ThreadPoolExecutor。通过查看源代码我们可以发现,它的继承结构为:
ThreadPoolExecutor extends AbstractExecutorService implements ExecutorService extends Executor
该类的主要核心方法如下:
execute():向线程池提交一个任务,交由线程池去执行;
submit():用来向线程池提交任务,可返回执行结果;
shutdown():关闭线程池,不接受新的任务,它会等待所有的任务全部执行完;
shutdownNow():关闭线程池,不接受新的任务,它会尝试去终止正在执行的任务;
三、Java线程池实现原理
1、线程池状态
RUNNING:线程池状态后的初始化状态;
SHUTDOWN:调用shutdown()方法之后线程池的状态;
STOP:调用shutdownNow()方法之后线程池的状态;
TERMINATED:当线程池处于SHUTDOWN或STOP状态,并且没有执行中的任务的时候,线程池状态会被置为TERMINATED;
2、任务的执行
当一个任务交给线程池之后,线程池会进行如下的一些处理:
如果当前线程池中的线程数目小于corePoolSize,则每来一个任务,就会创建一个线程去执行这个任务;
如果当前线程池中的线程数目>=corePoolSize,则每来一个任务,会尝试将其添加到任务缓存队列当中,若添加成功,则该任务会等待空闲线程将其取出去执行;若添加失败(一般来说是任务缓存队列已满),则会尝试创建新的线程去执行这个任务;
如果当前线程池中的线程数目达到maximumPoolSize,则会采取任务拒绝策略进行处理;
如果线程池中的线程数量大于corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止,直至线程池中的线程数目不大于corePoolSize;如果允许为核心池中的线程设置存活时间,那么核心池中的线程空闲时间超过keepAliveTime,线程也会被终止。
注:其中corePoolSize表示线核心池的大小,maximumPoolSize表示线程池能容纳的最大线程数量,keepAliveTime表示线程存活时间。
3、线程池中线程的初始化
在默认情况下,创建线程池之后,线程池中是没有线程的,需要提交任务之后才会创建线程。
4、线程池涉及到的几种队列(类型BlockingQueue<Runnable>)
1)、ArrayBlockingQueue:基于数组的先进先出队列,此队列创建时必须指定大小;
2)、LinkedBlockingQueue:基于链表的先进先出队列,如果创建时没有指定此队列大小,则默认为Integer.MAX_VALUE;
3)、synchronousQueue:这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务。
5、线程池的任务拒绝策略
当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize,如果还有任务到来就会采取任务拒绝策略,通常有以下四种策略:
ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务
6、线程池的关闭
shutdown():不会立即终止线程池,而是要等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务
shutdownNow():立即终止线程池,并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务
7、线程池容量的动态调整
ThreadPoolExecutor.setCorePoolSize:设置核心池大小
ThreadPoolExecutor.setMaximumPoolSize:设置线程池最大能创建的线程数目大小
四、Java线程池的使用
通过ThreadPoolExecutor创建线程池的方式为:ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 200, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<Runnable>(5));但是通常我们不这么做,而是使用Executors类中的几个静态方法来创建线程池:
Executors.newCachedThreadPool(); //创建一个缓冲池,缓冲池容量大小为Integer.MAX_VALUE
Executors.newSingleThreadExecutor(); //创建容量为1的缓冲池
Executors.newFixedThreadPool(int); //创建固定容量大小的缓冲池
具体Demo示例代码如下:
package com.tu.test;
import java.util.concurrent.ArrayBlockingQueue;
//import java.util.concurrent.ExecutorService;
//import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
//创建一个线程池
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(5, 10, 200, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(5));
//ExecutorService poolExecutor = Executors.newScheduledThreadPool(5);
//ExecutorService poolExecutor = Executors.newCachedThreadPool();
for (int i = 0;i<15;i++) {
MyPoolTask task = new MyPoolTask(i);
//向线程池提交任务
poolExecutor.execute(task);
// System.out.println("线程池中线程数目:"+poolExecutor.getPoolSize()+",队列中等待执行的任务数目:"+
// poolExecutor.getQueue().size()+",已执行完的任务数目:"+poolExecutor.getCompletedTaskCount());
}
//关闭线程池
poolExecutor.shutdown();
}
}
执行结果如下:
Task2正在执行。。。
Task1正在执行。。。
Task3正在执行。。。
Task10正在执行。。。
Task11正在执行。。。
Task14正在执行。。。
Task12正在执行。。。
Task0正在执行。。。
Task4正在执行。。。
Task13正在执行。。。
Task2执行结束。。。
Task5正在执行。。。
Task1执行结束。。。
Task3执行结束。。。
Task6正在执行。。。
Task7正在执行。。。
Task10执行结束。。。
Task8正在执行。。。
Task11执行结束。。。
Task9正在执行。。。
Task12执行结束。。。
Task14执行结束。。。
Task0执行结束。。。
Task4执行结束。。。
Task13执行结束。。。
Task5执行结束。。。
Task7执行结束。。。
Task6执行结束。。。
Task8执行结束。。。
Task9执行结束。。。
相关推荐
《JAVA核心技术 第十版 卷1》是Java编程领域中一本经典的教材,它全面而深入地探讨了Java语言的基础和核心概念。这本书的英文版,Core Java Volume I - Fundamentals, 10th Edition,由Cay S. Horstmann和Gary ...
1. **Java基础知识**:了解Java的历史、特点以及其与C++的区别。学习Java环境搭建,包括JDK的安装和配置,以及编写并运行第一个"Hello, World!"程序。 2. **语法基础**:深入理解Java的基本语法,如数据类型(基本...
1. **Java基础知识回顾**: - 变量与数据类型:包括基本数据类型(如int、double、char等)和引用数据类型(如类、接口、数组)。 - 运算符与表达式:包括算术、比较、逻辑、赋值等运算符的使用。 - 控制流程:...
《Java程序设计教程》是一本深入浅出的Java学习资源,通过PPT的形式,系统地讲解了Java编程的基础知识和核心概念。这份压缩包包含了多个章节的课件,包括jhtp4_17.ppt至jhtp4_18.ppt等多个文件,涵盖了广泛的Java...
1. **Java基础知识**:本书首先回顾了Java的基础,包括语法、数据类型、流程控制语句、类和对象等,确保读者具备坚实的编程基础。 2. **面向对象编程**:深入探讨Java的面向对象特性,如封装、继承和多态,以及接口...
### Java Threads 2rd #### 书名:Java Threads 2rd ...以上是《Java Threads 2rd》这本书的主要内容概述,涵盖了Java线程技术的各个方面,从基础知识到高级主题均有涉猎,旨在帮助读者全面掌握Java中的线程编程技术。
《Java程序设计(第2版)》是一本广泛应用于高等教育领域的教材,主要针对计算机科学与技术专业或相关专业学生,旨在教授Java编程语言的基础知识和高级特性。这本教材的内容通常涵盖以下几个核心知识点: 1. **Java...
12. **chap12_13.chm** - 第十二和十三章:这部分可能是综合应用或进阶主题,如设计模式、Java并发编程、JVM内存模型、垃圾收集机制等,或者是对前面章节的总结和回顾。 通过学习《thing in java》这本书,读者可以...
《CoreJava课件》是一份全面且深入的学习资源,涵盖了Java编程语言的核心概念和技术。这份课件共计十四章,每章都精心设计,旨在帮助...这份课件不仅适合初学者,也是经验丰富的开发者回顾和巩固基础知识的宝贵资料。
【描述】"jd-4-java1 Java1"虽然提供的信息非常简洁,但我们可以推测它可能是一个学习资源,可能是书籍、课程或者代码示例集合,专门针对Java初学者或作为回顾Java基础知识的参考资料。 【标签】为空,意味着没有...
在"MyNote-master"这个压缩包中,可能包含了这些知识点的详细讲解,通过阅读和整理这些笔记,可以系统地回顾和巩固Java JDK的相关知识。同时,通过对比不同来源的信息,分析和解决问题,能进一步提高编程技能。此外...
12. **API使用**:如Java标准库、第三方库(如Apache Commons、Guava等)的使用。 通过分析和运行这些项目,不仅可以复习Java编程知识,还能学习到如何组织和管理一个实际项目,这对于提升编程能力和适应未来工作...
4. **NIO基础知识**:介绍了NIO的基本概念,包括缓冲区(Buffer)、通道(Channel)、选择器(Selector)等。 5. **基于NIO的阻塞服务器**:利用NIO技术实现非阻塞I/O操作,提高服务器性能。 6. **基于NIO的非阻塞服务器**...
5.1 Android Intent基础知识 5.2 Android中可用的Intent 5.3 Intent的组成 5.3.1 Intent和数据URI 5.3.2 一般操作 5.3.3 使用extra信息 5.3.4 使用组件直接调用活动 5.3.5 Intent类别 5.3.6...
5.1 Android Intent基础知识 5.2 Android中可用的Intent 5.3 Intent的组成 5.3.1 Intent和数据URI 5.3.2 一般操作 5.3.3 使用extra信息 5.3.4 使用组件直接调用活动 5.3.5 Intent类别 5.3.6...