再来说一说线程池

       这段时间一直在忙着自己的事情,搞的非常尴尬,一直没能静下心来好好想想。不过还好,最近对于线程池的东西还是一直处于进步阶段。

        我还是习惯直接动嘴说说,以后万一想开了,也会贴很多源码上来,但是现在主要还是想打字来解释,毕竟源码很多时候来的更清晰,但是我这样写的目的也是等于加强自己的记忆,所以先不用源码来增加篇幅了。

        还是先new一个线程池开始吧。new ThreadPoolExecutor(0,0,0,null,new SynchronousQueue<Runnable>());0和null是我上一篇已经详细说的东西了,现在实在是懒得给他多一点赋值的心情了。对,没错,我是打算说一下最后这个队列的。

        这个队列,目前最常见的有三种(ArrayBlockingQueue,LinkedBlockingQueue,SynchronousQueue),在使用executors创建的线程池中,你会发现没有第一种,具体原因不得而知,可能是:一、限制的太死?因为array对列是固定缓存池大小的(因为没人会问这个队列是干嘛的了吧,好吧,我说一句,这个是用来缓存任务的,只有当任务填满缓存了,才会用到maxinumpoolsize,上一篇。。。)。这种固定死的方式会导致很多意想不到的拒绝(线程池对任务的拒绝措施,一般都是默认的----抛异常拒绝)。而且我感觉推荐使用executors也是有一种不在拒绝的味道(个人主观臆断,没什么依据,主要是从创建的几种线程池的内容中推断的,毕竟我只是一个渣渣,后面我会说一点点推理的依据)。二、设计不好(求不打脸,我这个瞎说的),看过源码的童鞋应该发现了,array队列的里面只用一把锁final修饰的。这样这个队列在添加和移除的时候都是同一把锁,也就是不能出现添加和移除的并发操作,我大致百度了一下,没有找到合理的解释。这样可能会在线程池频繁添加和移除的时候出现性能问题。当然这个是我瞎说的,不注意作为依据。

        那我们再来谈谈剩下的两个queue吧。linkedBlockingQueue,一看名字就知道,这个是链表的队列嘛,对,就是这样的,那有什么说的呢?首先说一下锁的问题,这个队列就很理智(233)的使用了两个final的lock(take和put),对嘛,进出分开嘛,当年我在化工厂里面看设计图的时候,就看到人家设计师说,人流物流进进出出严格分开滴,没错,程序就是要反应现实的,不然写程序不就找不到使用的价值了(继续瞎说)。然后再来一点不瞎说的。既然是链表,我们存取是不是可以使用双向链表尾放头取呢?可以,没错,人家就是这么玩的,是不是一点都不意外,你能想到的这么简单的东西,人家大牛早就实现了。那么,这样是不是就有一个很熟悉的生产者消费者模式出现了,哇塞,如果你能想到这里,那么和我这个渣渣同一水准了呢(2333),反正写东西的时候,瞎想一下,万一和大神想到一起去了呢。对,这里就是这样的。通过前面的两把锁(显示锁aqs实现的ReentrantLock,我打算下一次写一下这个),获取condition(用来休息的),然后每次存/取的时候,检查一下容量,如果满/亏,那么就休息一下。至于为什么是循环,那是因为这里有并发,每次醒来的时候,先循环一下,能不能拿到,拿不到就继续休息。如果拿到了,就去干活吧。take和put最后一行代码是叫醒对应的线程,这个是因为这个线程已经拿走了一个,所以让等着的put填进来。(这里我专门提一下的原因是我第一次就看错了,搞了半天才发现是自己atomicInteger的方法getAndDecrement搞错了---拿到旧值(我理解成了拿到增加之后的值了)),所以这里我专门提示一下。然后这个队列就没有太多可以说的了,而且实现也很简单,看一遍源码就知道了。

        剩下一个是SynchronousQueue,这个没有加blocking,是不是以为就不是阻塞的呢?这个队列很特殊,它是一个转移队列,自己不保存东西,也就是容量是0,。那他怎么玩的呢?首先通过内部transfer对象来实现(queue公平,stack非公平)队列。说好的不保存东西的呢,是的,任务过来了,它是不会保存的。那么他保存的是什么呢,没错,是空闲的线程。这个队列通过put的东西会一直阻塞自己,只有当下一个线程过来take之后才会继续自己的逻辑。所以当新任务来的时候,这个队列直接创建新的线程去执行,自己不缓存任务。而当空闲线程回来的时候,那就可以进队了,因为put就是await当前线程的,这个是通过lockResource也就是底层native方法的wait,因为这个队列没有使用aqs,直接是使用的cas算法,代码那叫一个复杂呀。不过慢慢也能看懂,就是node的进出队列。算是一个优化锁的实现,先自旋一会然后等待(根据cpu数定次数,如果单cpu,就不要自旋了,直接wait吧,其他的就是需要的),这个设计就非常合理,因为单cpu如果大量的自旋,会明显拖慢其他的线程。至于这个队列的公平模式和非公平模式,我就不细说了,感觉和锁的机制差不多,只是他使用了两种数据结构罢了。

        说了这么多废话,现在再说一下java的推荐的几种选择,单线程和固定容量的线程都是选择的是LinkedBlockingQueue,没有大小上限,默认是integer.MAX_VALUE(当然可以设置大小的),前面我说的不建议使用拒绝措施就是这里看到的,因为如果核心池和最大池固定了,就不再固定缓存的数量了,这样在正常的情况就不会有什么拒绝的机会了。至于cached的线程池,那还用说,虽然没有核心线程,但是我们最大线程多呀,也是integer.MAX_VALUE(其实线程池没有这么大的容量,因为线程池容量和状态是一个integer,32位,高位3个位置保存status,低位29个位置保存容量,这种设计,省了一个atmicinteger的对象,但是对于我这种渣渣,看起源码来,苦的一批),所以,这个缓存池也没有机会拒绝,对了,差点忘记说了,这个队列使用的就是SynchronousQueue,每次过来任务也不缓存了,直接创建新线程就可以了,反正我们线程多,用来了过期时间到了也自动销毁了。不过这种方法其实不是很好,因为对于任务时间长的任务,会出现大量的运行和就绪的线程,导致其他的线程运行速度受限,所以最好使用这个线程池的时候,执行的都是小任务。

        好了,线程池就到这里吧,其实很多线程池的东西可以写,但是写起来真的没完没了了,比如每一个线程的创建都是一个work,work不单单实现了runnable接口,还继承了aqs,没错,每一个任务本身就是一把锁,而且是排他锁。好了,大致就这么多了,下一篇,我们聊聊锁吧。


        

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

推荐阅读更多精彩内容