jdk1.5之前,所有的线程都是需要自己手动创建的,由jvm销毁,当请求过多的时候,频繁的创建和销毁线程是非常浪费资源的。jdk1.5为此做了优化,提供了

java.util.concurrent

包,该包下有个 Executor 接口,官方解释为:

执行已提交的 Runnable 任务的对象。此接口提供一种将任务提交与每个任务将如何运行的机制(包括线程使用的细节、调度等)分离开来的方法。通常使用 Executor 而不是显式地创建线程。

很明显,有这个这个东西,我们不需要自己手动 new Thread了。程序员只需要专注于任务就可以了,然后把任务交给executor,由他帮我们执行任务。

因此,我们可以非常自然的想到一个东西,那就是 线程池,ThreadPoolExecutor就是该接口的具体实现类。

我们的具体的线程池实现类。

public class ThreadPoolExecutor extends AbstractExecutorService

实现了通用的管理线程的方法。
public abstract class AbstractExecutorService implements ExecutorService

ExecutorService抽象了基本的管理线程的方法,如提交任务,关闭任务。
public interface ExecutorService extends Executor

而线程池有几个主体,线程管理器(线程池本身),工作线程(workThread)任务(runnable),等待队列。

简单来说,线程管理器维护一定数量的工作线程,将我们提交的任务交由工作线程完成,当池中没有空闲的工作线程时,交给等待队列中去。等待队列可以是先进先出,先进后出,具体策略由你自己来决定。当等待队列也慢了的时候,我们

当创建线程池时几个参数包含了线程池的一切

corePoolSize:
核心线程池数,线程池默认的工作线程数,线程池创建时,默认为0,只有来一个任务才创建一个线程。

maximumPoolSize:
线程池允许的最多线程数,当等待队列满了之后,这个参数才有意义。

keepAliveTime:
当池中的线程数大于核心线程数时,多余的线程在销毁之前会等待指定时间。

unit:
多余的线程等待的时间单位。

workQueue:
当核心线程数全部都在运行任务时,再次来的任务将被放到该等待队列中。此队列仅保持由 execute 方法提交的 Runnable 任务。
举个栗子来说名线程池根据参数运行的流程:
corePoolSize:5
maximumPoolSize:15(包含corePoolSize)
keepAliveTime:2
unit:秒
workQueue:数组型等待队列,最大的等待数为50

1.当我创建5个线程时,线程池将会一一创建核心线程数,
2.当第6个任务来临,而前面5个任务还没有完成是,线程池中没有线程了,那么线程池将会把这个任务放到任务workQueue中。
3.当第56个线程来临时,而核心线程还在运行,而workQueue中也已经饱和。此时,线程池会多创建一个线程来运行多出来的那一个任务
(具体哪一个任务根据你的策略来)。但是池中的线程数不能超过maximumPoolSize,包含核心数。
4.当第66个任务来临的时候,池中已经有15个线程在运行任务了,等待队列中也已经有50个线程在等待,因此 15+50=65 是ok的,但是再来一个66的
话那就不ok了,线程池直接回拒接你,抛出 RejectedExecutionException 错误。
测试代码如下:
public class Worker extends Thread {

private int i = 0;

@Override
public void run() {

while(i==0){
i++;
try {
Thread.currentThread().sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" run...");
}

}
}

//等待队列最大任务数为50
ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue<Runnable>(50);
//核心线程数:5 最大线程数:15 多余线程存活时间:2秒
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5,15,2,TimeUnit.SECONDS,arrayBlockingQueue);
// threadPoolExecutor.prestartAllCoreThreads();
System.out.println("池中的当前线程数 :" + threadPoolExecutor.getPoolSize());

//创建56个任务。
for(int i = 0 ; i < 65; i ++){
threadPoolExecutor.execute(new Worker());
}
System.out.println("==================over===============");

ArrayBlockingQueue<Runnable> blockingQueue = (ArrayBlockingQueue)threadPoolExecutor.getQueue();

System.out.println("池中的当前线程数 :" + threadPoolExecutor.getPoolSize());
System.out.println("曾经同时位于池中的最大线程数 :" + threadPoolExecutor.getLargestPoolSize());
System.out.println("等待队列中的任务数:" + blockingQueue.size());

输出:
池中的当前线程数 :0
==================over===============
池中的当前线程数 :15
曾经同时位于池中的最大线程数 :15
等待队列中的任务数:50
pool-1-thread-2  run...
pool-1-thread-5  run...
.....
Executors类中包含了很多静态方法创建多种不同类型的线程池。
1.创建可伸缩线程池。
2.创建定长线程池。
3.创建定长线程池,支持执行定制和周期性任务。
3.创建单例线程的线程池。
参考资料:
http://www.importnew.com/19011.html
http://blog.csdn.net/hsuxu/article/details/8985931
http://cuisuqiang.iteye.com/blog/2019372
---------------------
作者:helianus
来源:CSDN
原文:https://blog.csdn.net/helianus/article/details/78304733
版权声明:本文为博主原创文章,转载请附上博文链接!

多线程-Executors和Executor,线程池的更多相关文章

  1. 多线程(七)JDK原生线程池

    如同数据库连接一样,线程的创建.切换和销毁同样会耗费大量的系统资源.为了复用创建好的线程,减少频繁创建线程的次数,提高线程利用率可以引用线程池技术.使用线程池的优势有如下几点:        1.保持 ...

  2. Executor线程池框架

    Executor线程池框架 new Thread()的缺点 每次new Thread()耗费性能 调用new Thread()创建的线程缺乏管理,被称为野线程,而且可以无限制创建,之间相互竞争,会导致 ...

  3. Executor线程池

    Executor线程池框架: 使用线程池的优点: 1.重用存在的线程 2.减少对象创建.消亡的开销 3.性能佳 4.可有效控制最大并发线程数,提高系统资源的使用率 5.避免过多资源竞争,避免堵塞 6. ...

  4. 【搞定面试官】你还在用Executors来创建线程池?会有什么问题呢?

    前言 上文我们介绍了JDK中的线程池框架Executor.我们知道,只要需要创建线程的情况下,即使是在单线程模式下,我们也要尽量使用Executor.即: ExecutorService fixedT ...

  5. Executors、ThreadPoolExecutor线程池讲解

    官方+白话讲解Executors.ThreadPoolExecutor线程池使用 Executors:JDK给提供的线程工具类,静态方法构建线程池服务ExecutorService,也就是Thread ...

  6. java核心-多线程(6)-线程池-ThreadPoolExecutor

    1.java多线程编程少不了使用线程池,线程池相关的工具类所在jdk包,java.util.concurrent 2.使用示例 demo1 public class ThreadPoolDemo { ...

  7. Executor线程池的简单使用

    我们都知道创建一个线程可以继承Thread类或者实现Runnable接口,实际Thread类就是实现了Runnable接口. 到今天才明白后端线程的作用:我们可以开启线程去执行一些比较耗时的操作,类似 ...

  8. 基础线程机制--Executor线程池框架

    基础线程机制 Executor线程池框架 1.引入Executor的原因 (1)new Thread()的缺点 ​  每次new Thread()耗费性能 ​  调用new Thread()创建的线程 ...

  9. 三、VIP课程:并发编程专题->01-并发编程之Executor线程池详解

    01-并发编程之Executor线程池详解 线程:什么是线程&多线程 线程:线程是进程的一个实体,是 CPU 调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系 ...

  10. 第十章:Python高级编程-多线程、多进程和线程池编程

    第十章:Python高级编程-多线程.多进程和线程池编程 Python3高级核心技术97讲 笔记 目录 第十章:Python高级编程-多线程.多进程和线程池编程 10.1 Python中的GIL 10 ...

随机推荐

  1. TypeScript的HTML5游戏

    wildfirecode 自动化的基于TypeScript的HTML5游戏开发 自动化的开发流程 在HTML5游戏开发或者说在Web客户端开发中,对项目代码进行修改之后,一般来说,需要手动刷新浏览器来 ...

  2. 【LOJ】#2493. 「BJOI2018」染色

    题面 题解 推结论大题--然而我推不出什么结论 奇环显然是NO 如果一个联通块里有两个分离的环,也是NO 如果一个联通块里,点数为n,边数为m m <= n的时候,是YES m >= n ...

  3. 【AtCoder】ARC091

    C - Flip,Flip, and Flip...... 只有一个这一个是反面 只有一行那么除了两边以外都是反面 否则输出\((N - 2)*(M - 2)\) #include <bits/ ...

  4. PHP SMTP邮件发送(可加附件)

    <?php /** * @param $address mixed 收件人 多个收件人/或需要设置收件人昵称时为数组 array($address1,$address1)/array(array ...

  5. 【已解决】Chrome提示:"请停用以开发者模式运行的扩展程序"的解决办法

    chrome用户在安装了一些第三方的chrome插件后,每次打开浏览器的时候都会出现“请停用以开发者模式运行的扩展程序”的提示,只有每次点击取消之后才能正常使用扩展.如下图所示 那么有没有什么方法可以 ...

  6. P2870 [USACO07DEC]最佳牛线,黄金Best Cow Line, Gold

    P2870 [USACO07DEC]最佳牛线,黄金Best Cow Line, Gold我比赛的时候A了,luogu上25分,QAQ,又憨又傻的200+代码,我为什么要干电脑干的事情,无语了.如果左边 ...

  7. 【Ray Tracing in One Weekend 超详解】 光线追踪1-8 自定义相机设计

    今天,我们来学习如何设计自定义位置的相机 ready 我们只需要了解我们之前的坐标体系,或者说是相机位置 先看效果   Chapter10:Positionable camera 这一章我们直接用概念 ...

  8. Access数据库审计工具mdbtools

    Access数据库审计工具mdbtools   Access是Windows系统中常用的文件型数据库,广泛用于小型B/S和C/S系统中.在数据取证和Web渗透中,经常会遇到该类型的数据库文件.Kali ...

  9. python语法(三)— 循环

    上一篇,学习了python的判断语句,了解了python中如何直线分支语句,本文来学习循环语句.python中有两种循环while循环和for循环,当我们不知道循环次数时使用while循环,让我们知道 ...

  10. [AHOI2013]作业

    [AHOI2013]作业 题目大意: 给定一个长度为\(n(n\le10^5)\)的数列\(A(1\le A_i\le n)\).\(m(m\le10^6)\)次询问,每次询问区间\([l,r]\)内 ...