1. 1 不可撤销
  2. 2 小年兽 程嘉敏
  3. 3 手放开 李圣杰
  4. 4 迷人的危险3(翻自 dance flow) FAFA
  5. 5 山楂树之恋 程佳佳
  6. 6 summertime cinnamons / evening cinema
  7. 7 不谓侠(Cover 萧忆情Alex) CRITTY
  8. 8 神武醉相思(翻自 优我女团) 双笙
  9. 9 空山新雨后 音阙诗听 / 锦零
  10. 10 Wonderful U (Demo Version) AGA
  11. 11 广寒宫 丸子呦
  12. 12 陪我看日出 回音哥
  13. 13 春夏秋冬的你 王宇良
  14. 14 世界が终わるまでは… WANDS
  15. 15 多想在平庸的生活拥抱你 隔壁老樊
  16. 16 千禧 徐秉龙
  17. 17 我的一个道姑朋友 双笙
  18. 18 大鱼  (Cover 周深) 双笙
  19. 19 霜雪千年(Cover 洛天依 / 乐正绫) 双笙 / 封茗囧菌
  20. 20 云烟成雨(翻自 房东的猫) 周玥
  21. 21 情深深雨濛濛 杨胖雨
  22. 22 Five Hundred Miles Justin Timberlake / Carey Mulligan / Stark Sands
  23. 23 斑马斑马 房东的猫
  24. 24 See You Again Wiz Khalifa / Charlie Puth
  25. 25 Faded Alan Walker / Iselin Solheim
  26. 26 Natural J.Fla
  27. 27 New Soul Vox Angeli
  28. 28 ハレハレヤ(朗朗晴天)(翻自 v flower) 猫瑾
  29. 29 像鱼 王贰浪
  30. 30 Bye Bye Bye Lovestoned
  31. 31 Blame You 眠 / Lopu$
  32. 32 Believer J.Fla
  33. 33 书信 戴羽彤
  34. 34 柴 鱼 の c a l l i n g【已售】 幸子小姐拜托了
  35. 35 夜空中最亮的星(翻自 逃跑计划) 戴羽彤
  36. 36 慢慢喜欢你 LIve版(翻自 莫文蔚) 戴羽彤
  37. 37 病变(翻自 cubi) 戴羽彤
  38. 38 那女孩对我说 (完整版) Uu
  39. 39 绿色 陈雪凝
  40. 40 月牙湾 LIve版(翻自 F.I.R.) 戴羽彤
夜空中最亮的星(翻自 逃跑计划) - 戴羽彤
00:00 / 04:10

夜空中最亮的星 能否听清

那仰望的人 心底的孤独和叹息

夜空中最亮的星 能否记起

那曾与我同行 消失在风里的身影

我祈祷拥有一颗透明的心灵

和会流泪的眼睛

给我再去相信的勇气

越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请指引我靠近你

夜空中最亮的星 是否知道

那曾与我同行的身影 如今在哪里

夜空中最亮的星 是否在意

是等太阳先升起 还是意外先来临

我宁愿所有痛苦都留在心底

也不愿忘记你的眼睛

哦 给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行 哒~

我祈祷拥有一颗透明的心灵

和会流泪的眼睛 哦

给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行

多线程之线程池(上)

前言

最近一段时间,我们一直都在分享多线程相关知识,也一直有用线程池,但是一直没有介绍线程池相关知识,所以今天我们就先来看下线程池相关的知识点。

线程池

ThreadPool,线程池,顾名思义就是存放线程的池子,也是jdk1.5引入的。对我们而言,它的最主要优势就是简化了线程启动流程,让我们可以更方便地使用多线程,再也不用手动start线程,直接通过线程池提交我们的任务即可,而且合理使用线程池至于可以带来以下几个好处:

  • 降低资源消耗:复用线程,降低创建和销毁线程带来的资源消耗

  • 提高响应速度:使用线程池,省去了线程创建和初始化过程,所以任务可以更快执行

  • 提高线程的可管理性:可以直接通过线程池管理、监控、调度线程,线程管理更方便

常用线程池

常用的线程池有SingleThreadExecutorCachedThreadPoolScheduledThreadPoolFixedThreadPool,他们分别是单线程调度器,缓存线程池,定时任务线程池和固定线程池,他们都可以通过Executors创建,调用对应的静态方法即可,由于这一块的内容比较多,所以今天就简单提一下,后面专门讲一次。

自定义线程池

我们今天着重讲下自定义线程池,自定义线程池也很简单,直接new ThreadPoolExecutor() ,然后传入对应的参数即可,大家可以看下下面的示例:

int corePoolSize = 10;
int maximumPoolSize = 20;
long keepAliveTime = 1000;
TimeUnit unit = TimeUnit.MICROSECONDS;
BlockingDeque<Runnable> workQueue = new LinkedBlockingDeque<>();
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
for (int i = 0; i < 50; i++) {
    threadPoolExecutor.execute(() -> {
        String name = Thread.currentThread().getName();
        System.out.println("hello threadPool: "+ name);
    });
}
threadPoolExecutor.shutdown();

ThreadPoolExecutor有三个构造方法,至少需要三个参数

其中第一个参数是线程池的基本大小,当你提交一个任务到线程池时,线程池会创建一个线程来执行任务,即使又空闲的线程存在,线程池依然会启动一个新线程来执行当前任务,直到线程池中的线程数达到线程基本大小(corePoolSize);

第二个参数是线程池允许创建的最大线程数。如果工作队列(第三个参数)满了,且创建线程数已达到线程池基本大小,则线程池会继续创建新的线程来执行任务。如果你指定的工作队列是无界的,那这个参数也就失效了。

第三个参数就是线程池工作队列,就是当你需要执行的任务超过线程池基本大小的时候,会把超出部分放进工作队列,等待线程池基本线程资源释放。

下面我们分别验证以上三点,运行上面的示例代码:

在第一次循环的时候(i=0),我们发现线程池的size0,活动线程数也是0,任务队列也是0,完成任务数也是0,这也说明线程池在最开始的时候是没有创建线程的;

然后我们让他循环到第9次(i=8),这时候线程池已经被初始化,有8个线程(由于断点的原因,第9个线程尚未被创建),活动线程数5,完成执行的任务数3,任务队列还是0,说明确实在未达到线程池基本大小时,会不断创建新的线程;

我们继续执行,让他循环到第15次(i=14),可结果似乎和我们预期不一样,按照预期,线程池的size应该是10,活动线程数也是10,任务队列也是4,完成任务数可能不确定,所以这里肯定不能通过debug的方式来看了,因为debug停顿之后好多线程资源已经被释放,任务根本就不会堆积,所以任务队列就不会有数据:

所以这里我在线程池启动任务前加一行打印,打印线程池数据

然后在运行,就可以拿到运行数据:

这样的数据才是真实的,因为实际运行的时候,线程启动是非常快的,所以执行完成的任务数应该是0,等待任务数是4

我们前面设定的最大线程数是20,但是翻看运行记录,我发现线程池的大小始终是10,说明只要不打到任务队列的上限,并不会创建新的线程,这里我们把循环次数改为60,然后运行下:

但是依然没有创建新的线程,因为还是内没有达到任务队列上限,我们把循环次数再调大一点,调到70:

现在线程池的大小就变成了19,活动线程数19,但是这时候如果你继续调大循环次数,线程池就会报错了:

这个错误的原因就是线程池资源已经耗尽了,无法再接收新的任务了,这也就是说线程池能够处理的最大任务数是corePoolSize + maximumPoolSize + workQueue.size() ,当然,如果你的workQueue不设定大小,那永远都不会报这个错误,当然maximumPoolSize 也就无效了。

总结

原本打算线程池一次分享完的,但是实际分享过程中发现内容太多了(已经一千五百字了),所以今天就先到这里,明天再继续分享线程池其他内容。总的来说,今天的内容已经说明白了线程池很多基础的知识点(反正我自己觉得我都有好多收获),算是干货满满吧,你如果掌握了这些知识点,至少在使用线程池的过程中会少踩好多坑。好了,今天就先说这么多吧!

posted @ 2021-07-15 13:28  云中志  阅读(62)  评论(0编辑  收藏  举报