多线程-Executors和Executor,线程池

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
版权声明:本文为博主原创文章,转载请附上博文链接!

原文地址:https://www.cnblogs.com/GarfieldEr007/p/10230855.html

时间: 2024-11-06 18:31:26

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

JDK 源码解析 —— Executors ExecutorService ThreadPoolExecutor 线程池

零. 简介 Executors 是 Executor.ExecutorService.ThreadFactory.Callable 类的工厂和工具方法. 一. 源码解析 创建一个固定大小的线程池:通过重用共享无界队列里的线程来减少线程创建的开销.当所有的线程都在执行任务,新增的任务将会在队列中等待,直到一个线程空闲.由于在执行前失败导致的线程中断,如果需要继续执行接下去的任务,新的线程会取代它执行.线程池中的线程会一直存在,除非明确地 shutdown 掉. public static Exec

Executor线程池框架

Executor线程池框架 new Thread()的缺点 每次new Thread()耗费性能 调用new Thread()创建的线程缺乏管理,被称为野线程,而且可以无限制创建,之间相互竞争,会导致过多占用系统资源导致系统瘫痪. 不利于扩展,比如如定时执行.定期执行.线程中断 采用线程池的优点 重用存在的线程,减少对象创建.消亡的开销,性能佳 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞 提供定时执行.定期执行.单线程.并发数控制等功能 Executor的介绍

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

前言 上文我们介绍了JDK中的线程池框架Executor.我们知道,只要需要创建线程的情况下,即使是在单线程模式下,我们也要尽量使用Executor.即: ExecutorService fixedThreadPool = Executors.newFixedThreadPool(1); //此处不该利用Executors工具类来初始化线程池 但是,在<阿里巴巴Java开发手册>中有一条 [强制]线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方

JAVA程序设计(18.1)----- 1多线程轮流打印 线程调度 线程池 synchronized wait notify 内部类

1.两个线程 一个打印A 一个打印B 另两个线程轮流进行打印工作 多线程初级应用 线程调度  线程池(预先建立N个线程,需要的程序直接调用,执行完毕后归还回线程池,典型的以空间换时间 synchronized wait notify  内部类使用 package com.lovo; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 类:测试 wait notify 用

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

基础线程机制 Executor线程池框架 1.引入Executor的原因 (1)new Thread()的缺点 ???每次new Thread()耗费性能 ???调用new Thread()创建的线程缺乏管理,被称为野线程,而且可以无限制的创建,之间相互竞争,导致过多的系统资源被占用导致系统瘫痪,不利于定时执行,定期执行,线程中断. (2)采用线程池的优点 ???可以重用创建的线程,减少对象的创建,消亡的开销,性能更佳. ???可以有效的控制最大并发线程数,提高系统资源的利用率,避免过多的资源竞

C#多线程之旅(3)——线程池

v博客前言 先交代下背景,写<C#多线程之旅>这个系列文章主要是因为以下几个原因:1.多线程在C/S和B/S架构中用得是非常多的;2.而且多线程的使用是非常复杂的,如果没有用好,容易造成很多问题. v写在前面 多线程,有利也有弊,使用需谨慎. v正文开始 原文地址:C#多线程之旅(3)——线程池 C#多线程之旅目录: C#多线程之旅(1)——介绍和基本概念 C#多线程之旅(2)——创建和开始线程 C#多线程之旅(3)——线程池 C#多线程之旅(4)——同步本质 ...... 一.介绍 无论你什

C# 多线程的自动管理(线程池) 基于Task的方式

C# 多线程的自动管理(线程池) 在多线程的程序中,经常会出现两种情况:    1. 应用程序中线程把大部分的时间花费在等待状态,等待某个事件发生,然后给予响应.这一般使用 ThreadPool(线程池)来解决.     2. 线程平时都处于休眠状态,只是周期性地被唤醒.这一般使用 Timer(定时器)来解决. ThreadPool 类提供一个由系统维护的线程池(可以看作一个线程的容器),该容器需要 Windows 2000 以上系统支持,因为其中某些方法调用了只有高版本的Windows 才有的

【转载】5天不再惧怕多线程——第五天 线程池

说到多线程,不可不说线程池,C#中关于池的概念很多,今天来整理下ThreadPool的使用. 是的,如果你很懒,如果你的执行任务比较短,如果你不想对线程做更精细的控制,那么把这些繁琐的东西丢给线程池吧. 一:ThreadPool 好了,下面看看TheadPool下有哪些常用的方法. 1:GetMaxThreads,GetMinThreads 首先我们肯定好奇线程池到底给我们如何控制线程数,下面就具体的看一看. 1 class Program 2 { 3 static void Main(stri

Executors、ThreadPoolExecutor线程池使用

Executors:JDK给提供的线程工具类,静态方法构建线程池服务ExecutorService,也就是ThreadPoolExecutor,使用默认线程池配置参数. 建议:对于大用户,高并发,不易掌控的项目,不建议使用Executors来创建线程池对象. 对于易于掌控且并发数不高的项目,可以考虑Executors. ThreadPoolExecutor:线程池对象,实现ExecutorService接口,可以自定义线程池核心线程数.最大线程数.空闲时间.缓冲队列等. 建议:大用户,高并发,不