Executor 线程池

1、什么是线程池:  java.util.concurrent.Executors提供了一个 java.util.concurrent.Executor接口的实现用于创建线程池

多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力。

假设一个服务器完成一项任务所需时间为:T1 创建线程时间,T2 在线程中执行任务的时间,T3 销毁线程时间。

如果:T1 + T3 远大于 T2,则可以采用线程池,以提高服务器性能。

一个线程池包括以下四个基本组成部分:

1、线程池管理器(ThreadPool):用于创建并管理线程池,包括 创建线程池,销毁线程池,添加新任务;

2、工作线程(PoolWorker):线程池中线程,在没有任务时处于等待状态,可以循环的执行任务;

3、任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;

4、任务队列(taskQueue):用于存放没有处理的任务。提供一种缓冲机制。

线程池技术正是关注如何缩短或调整T1,T3时间的技术,从而提高服务器程序性能的。它把T1,T3分别安排在服务器程序的启动和结束的时间段或者一些空闲的时间段,这样在服务器程序处理客户请求时,不会有T1,T3的开销了。

线程池不仅调整T1,T3产生的时间段,而且它还显著减少了创建线程的数目,看一个例子:

假设一个服务器一天要处理50000个请求,并且每个请求需要一个单独的线程完成。在线程池中,线程数一般是固定的,所以产生线程总数不会超过线程池中线程的数目,而如果服务器不利用线程池来处理这些请求则线程总数为50000。一般线程池大小是远小于50000。所以利用线程池的服务器程序不会为了创建50000而在处理请求时浪费时间,从而提高效率。

线程池的作用:

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

根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果;少了浪费了系统资源,多了造成系统拥挤效率不高。用线程池控制线程数量,其他线程排队等候。一个任务执行完毕,再从队列的中取最前面的任务开始执行。若队列中没有等待进程,线程池的这一资源处于等待。当一个新任务需要运行时,如果线程池中有等待的工作线程,就可以开始运行了;否则进入等待队列。

为什么要用线程池:

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

2.可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。

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

线程池介绍

package com.cmy.Executor.demo1;

import java.util.concurrent.*;

/**

* 线程复用:线程池(为了避免系统频繁的创建和销毁线程,我们可以将创建的线程进行复用)

* JDK对线程池的支持:

*       JDK提供的Executors框架,可以让我们有效的管理和控制我们的线程,其本质上就是一个线程池

*       Executor接口的继承关系如下所示:

*                       Executor

*                          ↑

*                    ExecutorService

*                ↑                        ↑

*     AbstractExecutorService    ScheduledExecutorService

*                ↑                        ↑

*      ThreadPoolExecutor                 ↑

*                ↑                        ↑

*                 ScheduledThreadPoolExecutor

*

*

*    Executors类常用方法如下:

*

*    1、newFixedThreadPool:该方法返回一个固定线程数量的线程池;

*

*    2、newSingleThreadExecutor:该方法返回一个只有一个现成的线程池;

*

*    3、newCachedThreadPool:返回一个可以根据实际情况调整线程数量的线程池;

*

*    4、newSingleThreadScheduledExecutor:该方法和newSingleThreadExecutor的区别是给定了时间执行某任务的功能,可以进行定时执行等;

*

*    5、newScheduledThreadPool:在4的基础上可以指定线程数量。

*

*

*    查看Executors类的源码如下: 例如newFixedThreadPool (同学们可自主查看)

*

*    以下为:newFixedThreadPool的实现:

*            public static ExecutorService newFixedThreadPool(int nThreads) {

*                   return new ThreadPoolExecutor(nThreads, nThreads,

*                      0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());

*            }

*

*    本质上是创建了ThreadPoolExecutor的实例而已!

*

*    ThreadPoolExecutor构造参数如下:

*        public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize, 核心线程池大小

long keepAliveTime,  线程最大容量

TimeUnit unit,       空闲时,线程的存活时间

ThreadFactory,       线程工厂

BlockingQueue<Runnable> workQueue, 任务队列

RejectedExecutionHandler handler) {  线程的拒绝策略

this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,

Executors.defaultThreadFactory(), handler);

}

*

*

*

*/

public class ThreadPoolDemo {

public static void main(String[] args){

/*在此 根据alibaba编码规范的提示

‘不推荐使用Executors中的方法创建线程池 而是推荐创建ThreadPoolExecutor实例的方式’

以下为alibaba介绍:

线程池不允许使用Executors去创建,而是使用ThreadPoolExecutor的方式,这样做可以规避很多风险

说明:各个方法的弊端

newFixedThreadPool和newSingleThreadExecutor:

主要问题是堆积的请求处理队列可能会耗费非常大的内存

newCachedThreadPool和newScheduledThreadPool

主要问题是线程最大数Integer.MAX_VALUE 可能会创建过多的线程 导致资源浪费

*/

//不推荐做法:ExecutorService service=Executors.newFixedThreadPool(4); //获取拥有4条线程的线程池

//推荐做法

ExecutorService service=new ThreadPoolExecutor(2,

2,

0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<>(10),Executors.defaultThreadFactory());

for (int i=0;i<10;i++){

int index=i;

//使用线程池中的线程重复打印index的值

service.submit(()->

System.out.println(Thread.currentThread().getName()+" i:"+index+"service"));

}

service.shutdown();//线程停止运行

}

}

线程池的使用

package com.cmy.Executor.demo2;

//使用submit函数带来的问题

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.Future;

public class ThreadPoolDemo {

public static void main(String[] args){

ExecutorService service= Executors.newFixedThreadPool(4);

for(int i=0;i<5;i++){

int index=i;

//此处index的初值为0 但控制台上不会输出任何异常(原因 内部捕获了异常)

//service.submit(()-> Calc(100,index));

//1:替换为execute

//service.execute(()->Calc(100,index));

//2:或者使用Future模式 自定义异常捕获和信息

Future future=service.submit(()->Calc(100,index));

try {

future.get();

} catch (Exception e) {

System.out.println("我是异常信息");

}

}

service.shutdown();

}

public static void Calc(int a,int b){

double c=a/b;

System.out.println(c);

}

}

原文地址:https://www.cnblogs.com/zhu12345/p/9770482.html

时间: 2024-07-31 22:55:51

Executor 线程池的相关文章

Executor线程池框架

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

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

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

2,Executor线程池

一,Executor框架简介 在Java 5之后,并发编程引入了一堆新的启动.调度和管理线程的API.Executor框架便是Java 5中引入的,其内部使用了线程池机制,它在java.util.cocurrent 包下,通过该框架来控制线程的启动.执行和关闭,可以简化并发编程的操作. Executor框架包括:线程池,Executor,Executors,ExecutorService,CompletionService(异步任务),Future,Callable等. 二,Executor接口

多线程--Executor线程池框架

Executor的介绍 在Java 5之后,并发编程引入了一堆新的启动.调度和管理线程的API.其内部使用了线程池机制,它在java.util.cocurrent 包下,通过该框架来控制线程的启动.执行和关闭,可以简化并发编程的操作.因此,在Java 5之后,通过Executor来启动线程比使用Thread的start方法更好,除了更易管理,效率更好(用线程池实现,节约开销)外,还有关键的一点:有助于避免this逃逸问题——如果我们在构造器中启动一个线程,因为另一个任务可能会在构造器结束之前开始

Executor线程池只看这一篇就够了

线程池为线程生命周期的开销和资源不足问题提供了解决方 案.通过对多个任务重用线程,线程创建的开销被分摊到了多个任务上. 线程实现方式 Thread.Runnable.Callable //实现Runnable接口的类将被Thread执行,表示一个基本任务 public interface Runnable { //run方法就是它所有内容,就是实际执行的任务 public abstract void run(); } //Callable同样是任务,与Runnable接口的区别在于它接口泛型,同

Executor线程池原理详解

线程池 线程池的目的就是减少多线程创建的开销,减少资源的消耗,让系统更加的稳定.在web开发中,服务器会为了一个请求分配一个线程来处理,如果每次请求都创建一个线程,请求结束就销毁这个线程.那么在高并发的情况下,就会有大量线程创建和销毁,这就会降低系统的效率.线程池的诞生就是为了让线程得到重复使用,减少了线程创建和销毁的开销,减少了线程的创建和销毁自然的就提高了系统的响应速度,与此同时还提高了线程的管理性,使线程可以得到统一的分配,监控和调优. 线程创建和销毁为什么会有开销呢,因为我们java运行

Java并发编程——Executor接口及线程池的使用

在如今的程序里,单线程的程序,应该已经比较少了,而Java语言是内置支持多线程并发的,大家都说Java语言内置支持多线程,非常非常的强大和方便,但一直没有深入研究jdk内concurrent包.今天就认真学习了一下java.util.concurrent包,发现jdk多线程编程果然是强大和方便.本文是学习java.util.concurrent包内线程池及相关接口的一些总结. 任务接口抽象 Runnable接口 在java.lang包内,为多线程提供了Runnable接口. public int

Java 线程池(一):开篇及Executor整体框架介绍

一.开篇 线程池.数据库连接池,在平时的学习中总能接触到这两个词,但它们到底是什么?和线程,数据库连接有什么关系?为什么需要“池”?“池”的概念及作用是什么?要弄清楚这些问题,就要深入到“池”的实现中去. 之前找实习工作时,时常有面试官问这类问题,自己平时知道如何使用Java的Executor线程池框架,但是具体的细节还真没感受,所以打算开始试着研究一下Executor线程池框架. 废话到此打住,正式开始! 二.Executor整体框架 让我们先站在一个较高的角度俯视一下Java线程池的整体结构

【转】线程池体系介绍及从阿里Java开发手册学习线程池的正确创建方法

jdk1.7中java.util.concurrent.Executor线程池体系介绍 java.util.concurrent.Executor : 负责线程的使用与调度的根接口  |–ExecutorService:Executor的子接口,线程池的主要接口  |–ThreadPoolExecutor:ExecutorService的实现类  |–ScheduledExecutorService:ExecutorService的子接口,负责线程的调度  |–ScheduledThreadPo