并发与高并发课程学习笔记(10)

线程池

首先是不推荐使用传统的new Thread,来创建线程。

1.每次new Thread新建对象,性能差。

2.线程缺乏统一的管理,可能无限制的新建线程,相互竞争,有可能占用过多的系统资源导致死机或oom。

3.缺少更多的功能,如更多执行,定期执行,线程中断

关于使用线程池的好处

1.重用存在的线程,减少对象创建,消亡的开销,性能佳

2.可以有效的控制最大并发线程数,提高系统资源利用率,同时可以避免过多的资源竞争,避免阻塞。

3.提供定时执行,定期执行,单线程,并发数控制等功能

Executor

Executor是一个接口,跟线程池有关的基本都要跟他打交道,Executor接口很简单,只有一个execute方法。

ExecutorService是Executor的子接口,增加了一些常用的对线程的控制方法,之后使用线程池主要也是使用这些方法。

AbstractExecutorService是一个抽象类。ThreadPoolExecutor就是实现了这个类。

ThreadPoolExecutor

常用的构造方法:

ThreadPoolExecutor(int corePoolSize,

                        int maximumPoolSize,

                        long keepAliveTime,

                        TimeUnit unit,

                        BlockingQueue workQueue)

ThreadPoolExecutor(int corePoolSize,

                        int maximumPoolSize,

                        long keepAliveTime,

                        TimeUnit unit,

                        BlockingQueue workQueue,

                        ThreadFactory threadFactory)

ThreadPoolExecutor(int corePoolSize,

                        int maximumPoolSize,

                        long keepAliveTime,

                        TimeUnit unit,

                        BlockingQueue workQueue,

                        RejectedExecutionHandler handler)

ThreadPoolExecutor(int corePoolSize,

                        int maximumPoolSize,

                        long keepAliveTime,

                        TimeUnit unit,

                        BlockingQueue workQueue,

                        ThreadFactory threadFactory,

                        RejectedExecutionHandler handler)

corePoolSize

核心线程数,默认情况下核心线程会一直存活,即使处于闲置状态也不会受存keepAliveTime限制。除非将allowCoreThreadTimeOut设置为true。

maximumPoolSize

线程池所能容纳的最大线程数。超过这个数的线程将被阻塞。当任务队列为没有设置大小的LinkedBlockingDeque时,这个值无效。

keepAliveTime

非核心线程的闲置超时时间,超过这个时间就会被回收。

unit

指定keepAliveTime的单位,如TimeUnit.SECONDS。当将allowCoreThreadTimeOut设置为true时对corePoolSize生效。

workQueue

线程池中的任务队列.

常用的有三种队列,SynchronousQueue,LinkedBlockingDeque,ArrayBlockingQueue。

threadFactory

线程工厂,提供创建新线程的功能。ThreadFactory是一个接口,只有一个方法

public interfaceThreadFactory{

        Thread newThread(Runnable r); //通过线程工厂可以对线程的一些属性进行定制。

}

RejectedExecutionHandler

RejectedExecutionHandler也是一个接口,只有一个方法

public interfaceRejectedExecutionHandler{ 

     void rejectedExecution(Runnable var1, ThreadPoolExecutor var2);

}

当线程池中的资源已经全部使用,添加新线程被拒绝时,会调用RejectedExecutionHandler的rejectedExecution方法。


线程池规则

线程池的线程执行规则跟任务队列有很大的关系。

下面都假设任务队列没有大小限制:

    1.如果线程数量<=核心线程数量,那么直接启动一个核心线程来执行任务,不会放入队列中。

    2.如果线程数量>核心线程数,但<=最大线程数,并且任务队列是LinkedBlockingDeque的时候,超过核心线程数量的任务会放在任务队列中排队。

    3.如果线程数量>核心线程数,但<=最大线程数,并且任务队列是SynchronousQueue的时候,线程池会创建新线程执行任务,这些任务也不会被放在任务队列中。这些线程属于非核心线程,在任务完成后,闲置时间达到了超时时间就会被清除。

    4.如果线程数量>核心线程数,并且>最大线程数,当任务队列是LinkedBlockingDeque,会将超过核心线程的任务放在任务队列中排队。也就是当任务队列是LinkedBlockingDeque并且没有大小限制时,线程池的最大线程数设置是无效的,他的线程数最多不会超过核心线程数。

    5.如果线程数量>核心线程数,并且>最大线程数,当任务队列是SynchronousQueue的时候,会因为线程池拒绝添加任务而抛出异常。

任务队列大小有限时:

    1.当LinkedBlockingDeque塞满时,新增的任务会直接创建新线程来执行,当创建的线程数量超过最大线程数量时会抛异常。

    2.SynchronousQueue没有数量限制。因为他根本不保持这些任务,而是直接交给线程池去执行。当任务数量超过最大线程数时会直接抛异常。

线程池的状态


RUNNING:在RUNNING状态下线程池可以处理新提交的任务,也可以处理请求队列中的任务

SHUTDOWN:在该状态下线程池不会接收新提交的任务,但是可以继续处理阻塞队列中的任务,由线程池调用shutdown()方法转换

STOP:在该状态下线程池不会接收新提交的任务,也不会继续处理阻塞队列中任务,正在执行中的任务也会中断,由RUNNING状态调用shutdownNow()方法转换

TIDYING:在SHUTDOWN状态下阻塞队列为空或STOP状态下线程池中工作线程为0时转换4

TERMINATED:由TIDYING状态下自动转换,不需关心

线程池提供的常用方法

execute():提交任务,交给线程池执行

submit():提交任务,能够返回执行结果 相当于execute+Future

shutdown():关闭线程池,等待任务都执行完毕

shutdownNow():关闭线程池,不等待任务执行完毕

getTaskCount():线程池已执行和未执行的任务总数

getCompeletedTaskCount():已完成的任务数量

getPoolSize():线程池当前的线程数量

getActiveCount():当前线程池中正在执行任务的线程数量

线程池-Executors框架接口

Executors.newCachedThreadPool   //创建一个可缓存的线程池,如果线程池超过了可选择的需要,可以灵活回收空闲线程,如果没有可回收的则创建新的线程

Executors.newFixedThreadPool  //创建一个定长线程池,可以控制最大并发数,超出的线程会在队列中等待

Executors.newScheduledThreadPool  //创建一个定长线程池,它支持定时,以及周期的任务执行

Executors.newSingleThreadExecutor  //创建一个单线程的线程池,它只会用唯一的一个工作线程,保证所有任务按指定顺序执行

例子:

ExecutorService executorService = Executors.newCachedThreadPool();  //初始化线程池

executorService.execute(new Runnable() {    //线程执行方法1

        @Override

        public void run(){

            log.info("task:{}",index);

        }

});

executorService.execute(new Thread());  //线程执行方法2

executorService.shutDown();  //使用线程池后一定要释放线程池,切记

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容

  • Java中对线程池提供了很好的支持,有了线程池,我们就不需要自已再去创建线程。如果并发的线程数量很多,并且每个线程...
    sunny4handsome阅读 714评论 0 2
  • 【JAVA 线程】 线程 进程:是一个正在执行中的程序。每一个进程执行都有一个执行顺序。该顺序是一个执行路径,或者...
    Rtia阅读 2,702评论 2 20
  • layout: posttitle: 《Java并发编程的艺术》笔记categories: Javaexcerpt...
    xiaogmail阅读 5,728评论 1 19
  • 深入分析线程池 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如...
    史路比阅读 444评论 0 1
  • 神仙与凡人恋爱千古一套路,都是仙女留恋人间美景下凡洗澡,凡人有点英俊才华加耍点小流氓偷藏仙女的衣服。遭天庭上一些吃...
    落桑Chen阅读 304评论 5 2