博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
11、多线程(三) -- 线程池
阅读量:6280 次
发布时间:2019-06-22

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

一、线程池

1.1、简介

线程的使用在java中占有极其重要的地位,在jdk1.4极其之前的jdk版本中,关于线程池的使用是极其简陋的。在jdk1.5之后这一情况有了很大的改观。

Jdk1.5之后加入了java.util.concurrent包,这个包中主要介绍java中线程以及线程池的使用。为我们在开发中处理线程的问题提供了非常大的帮助。

1.2、线程池

1、线程池的作用

线程池的作用就是限制系统中执行线程的数量。

根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果,减少系统资源的浪费以及系统拥挤导致销量不高的问题。

用线程池控制线程数量,其他线程排队等候。一个任务执行完毕,再从队列的中取最前面的任务开始执行。若队列中没有等待进程,

线程池的这一资源处于等待。当一个新任务需要运行时,如果线程池中有等待的工作线程,就可以开始运行了;否则进入等待队列。

2、为什么使用线程池

1.减少创建和销毁线程的次数,每个工作线程都可以被重复利用,可以执行多个任务。

2.可以根据系统的承受能力,在调整线程池中工作线程的数目,防止因为消耗过多的内存,超出服务器承受上限。

Java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是ExecutorService。

要配置一个线程池是比较复杂的,尤其是对于线程池的原理不是很清楚的情况下,很有可能配置的线程池不是较优的,

因此在Executors类里面提供了一些静态工厂,生成一些常用的线程池。

1.3、四种常用线程池

1、newSingleThreadExecutor

创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。

如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行

myThread.java

public class MyThread extends Thread {        public void run() {                System.out.println(Thread.currentThread().getName() + "正在执行...");    }    }

TestSingleThreadExecutor.java

public class MyThread {    public static void main(String[] args) {                // 创建一个可重用固定线程数的线程池        ExecutorService pool = Executors.newSingleThreadExecutor();                // 创建实现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

创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,

如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。

public class MyThread {        public static void main(String[] args){                ExecutorService pool = Executors.newFixedThreadPool(2);                // 创建实现Runnable接口对象        MyThread t1 = new MyThread();        MyThread t2 = new MyThread();        MyThread t3 = new MyThread();        MyThread t4 = new MyThread();        MyThread t5 = new MyThread();                pool.execute(t1);        pool.execute(t2);        pool.execute(t3);        pool.execute(t4);        pool.execute(t5);                // 关闭线程池        pool.shutdown();    }}

运行结果:

 

3、newCachedThreadPool

创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,

此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。

public class MyThread {        public static void main(String[] args){            ExecutorService pool = Executors.newCachedThreadPool();                MyThread t1 = new MyThread();        MyThread t2 = new MyThread();        MyThread t3 = new MyThread();        MyThread t4 = new MyThread();        MyThread t5 = new MyThread();                pool.execute(t1);        pool.execute(t2);        pool.execute(t3);        pool.execute(t4);        pool.execute(t5);                pool.shutdown();    }}

运行结果:

4、newScheduledThreadPool

创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。

public class MyThread {        public static void main(String[] args){                ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);        pool.scheduleAtFixedRate(new Runnable() { // 每个一段时间触发一次public void run() {
System.out.println("================"); } }, 1000, 5000, TimeUnit.MILLISECONDS); pool.scheduleAtFixedRate(new Runnable() {
//每隔一段时间打印系统时间,证明两者是互不影响的public void run() {
System.out.println(System.nanoTime()); } }, 1000, 2000, TimeUnit.MILLISECONDS); }}

运行结果

1.4、ThreadPoolExecutor

ThreadPoolExecutor的完整构造方法的签名是:

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue
workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
  • corePoolSize - 池中所保存的线程数,包括空闲线程。
  • maximumPoolSize-池中允许的最大线程数。
  • keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
  • unit - keepAliveTime 参数的时间单位。
  • workQueue - 执行前用于保持任务的队列。此队列仅保持由 execute方法提交的 Runnable任务。
  • threadFactory - 执行程序创建新线程时使用的工厂。
  • handler - 由于超出线程范围和队列容量而使执行被阻塞时所使用的处理程序。

ThreadPoolExecutor是Executors类的底层实现。

在JDK文档中有如此一段话:

强烈建议程序员使用较为方便的Executors工厂方法Executors.newCachedThreadPool()(无界线程池,可以进行自动线程回收)、

Executors.newFixedThreadPool(int)(固定大小线程池)、Executors.newSingleThreadEcecutor()(单个后台线程)。

后面的比较复杂,在进阶时深入研究和分析。

 

转载于:https://www.cnblogs.com/pengjingya/p/5657882.html

你可能感兴趣的文章
nginx反向代理
查看>>
操作系统真实的虚拟内存是什么样的(一)
查看>>
hadoop、hbase、zookeeper集群搭建
查看>>
python中一切皆对象------类的基础(五)
查看>>
modprobe
查看>>
android中用ExpandableListView实现三级扩展列表
查看>>
%Error opening tftp://255.255.255.255/cisconet.cfg
查看>>
java读取excel、txt 文件内容,传到、显示到另一个页面的文本框里面。
查看>>
《从零开始学Swift》学习笔记(Day 51)——扩展构造函数
查看>>
python多线程队列安全
查看>>
[汇编语言学习笔记][第四章第一个程序的编写]
查看>>
android 打开各种文件(setDataAndType)转:
查看>>
补交:最最原始的第一次作业(当时没有选上课,所以不知道)
查看>>
Vue实例初始化的选项配置对象详解
查看>>
PLM产品技术的发展趋势 来源:e-works 作者:清软英泰 党伟升 罗先海 耿坤瑛
查看>>
vue part3.3 小案例ajax (axios) 及页面异步显示
查看>>
浅谈MVC3自定义分页
查看>>
.net中ashx文件有什么用?功能有那些,一般用在什么情况下?
查看>>
select、poll、epoll之间的区别总结[整理]【转】
查看>>
CSS基础知识(上)
查看>>