当前位置:   article > 正文

线程池四种使用方式的实现及详细介绍(必看):_线程池启动的四种方式

线程池启动的四种方式

说明:本文对线程池的四种使用方式分别进行了实现,每种方式的详细介绍及关键点在代码的备注中

建议学习之前先参考:深入理解线程和线程池(图文详解)一文

  1. import java.text.SimpleDateFormat;
  2. import java.util.Date;
  3. import java.util.concurrent.*;
  4. public class Main {
  5. public static void main(String[] args) throws ExecutionException, InterruptedException {
  6. //线程池的四种使用方式(说明及关键点在实现方法中):
  7. //方式一:
  8. newCachedThreadPool();
  9. //方式二:
  10. // fixdThreadPool(5);
  11. //方式三:
  12. // newScheduledThreadPool(6);
  13. //方式四
  14. // newSingleThreadExecutor();
  15. }
  16. //方式一:newCachedThreadPool
  17. // 可缓存的线程池,该线程池中“没有核心线程,非核心线程的数量为无限大”,(核心线程在没用时候也不回收)
  18. // 就是说当有需要时创建线程来执行任务,没有需要时“回收”线程,适用于耗时少,任务量大的情况。
  19. //注意:线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。
  20. // 加上//****处那段代码就是体现此特点
  21. private static void newCachedThreadPool() throws ExecutionException, InterruptedException {
  22. ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
  23. for (int i = 0; i < 20; i++) {//线程池中线程数可以有无限大个
  24. // //**** 线程先睡一秒,再执行。由于睡一秒的过程前面线程已经执行完毕,所以不用开启新的线程,直接复用前面线程即可。
  25. // 所以才会重复用第一个线程
  26. // final int index = i;
  27. // try {
  28. // Thread.sleep(index * 1000);
  29. // }
  30. // catch (InterruptedException e) {
  31. // e.printStackTrace();
  32. // }
  33. //执行线程的方法1:调用runnableh中的run方法,此方法不向客户端返回执行结果
  34. cachedThreadPool.execute(new Runnable() {
  35. @Override
  36. public void run() {
  37. System.out.println("执行线程:" + Thread.currentThread().getName());
  38. }
  39. });
  40. }
  41. }
  42. //方式二:fixdThreadPool
  43. // 定长的线程池,“有核心线程,核心线程的即为最大的线程数量,没有非核心线程”
  44. // 创建一个定长线程池,超出的线程会在队列中等待,即使线程空闲也不会回收。
  45. //注意:1.此处线程池传入创建的线程有5个,但是有十个任务等待执行,先FIFO的顺序执行前五个线程,后五个在队列中等待。
  46. // 前五个线程执行完毕后再按照FIFO的顺序执行。
  47. // 2.定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()。可参考PreloadDataCache。
  48. private static void fixdThreadPool(int size) throws ExecutionException, InterruptedException {
  49. ExecutorService executorService = Executors.newFixedThreadPool(size);
  50. for (int i = 0; i < 10; i++) {
  51. //3.此处算法在线程执行直线进行睡眠,但是不会像newCatchThreadPool中那样重复在执行线程1,
  52. // 因为这里线程直接是创建了固定大小的,直接用(不用也不会回收)
  53. final int index = i;
  54. try {
  55. Thread.sleep(index * 1000);
  56. } catch (InterruptedException e) {
  57. e.printStackTrace();
  58. }
  59. //执行线程的方法2:调用Callable中的call方法,此方法可以向客户端返回执行结果
  60. Future<Integer> task = executorService.submit(new Callable<Integer>() {
  61. @Override
  62. public Integer call() throws Exception {
  63. System.out.println("执行线程:" + Thread.currentThread().getName());
  64. return null;
  65. }
  66. });
  67. System.out.println("第" + i + "次计算,结果:" + task.get());
  68. }
  69. }
  70. //方式三:newScheduledThreadPool,创建一个定长的线程池,支持定时及周期性任务执行
  71. private static void newScheduledThreadPool(int size) {
  72. ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(size);
  73. Date d = new Date();
  74. SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  75. System.out.println(df.format(d));
  76. //法一:schedule()延迟一定时间后执行任务
  77. //参数1:为执行的任务;参数2:任务的延迟间隔;参数3:为延迟执行的时间单位:
  78. scheduledExecutorService.schedule(new Runnable() {
  79. @Override
  80. public void run() {
  81. Date d = new Date();
  82. SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  83. System.out.println(df.format(d));
  84. System.out.println("执行线程:" + Thread.currentThread().getName());
  85. }
  86. }, 10, TimeUnit.SECONDS); //表示线程延迟十秒执行,任务只执行一次
  87. //法二:scheduleAtFixedRate(...):按指定频率周期执行某个任务。如12:00执行第一次,15:00执行第二次,18:00执行第三次...
  88. //(个人认为与法三的区别是:每个任务的开始时间是以一定周期开始的,后面任务开始时可能前面任务还未完成。
  89. // 而法三则是在前面任务完成的时间点上延迟一定时间执行)
  90. // 参数1:为执行的任务;参数2:初始任务延迟时间;参数3:执行的周期;参数4:为延迟执行的时间单位:
  91. // scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
  92. // @Override
  93. // public void run() {
  94. // Date d = new Date();
  95. // SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  96. // System.out.println(df.format(d));
  97. // System.out.println("执行线程:"+Thread.currentThread().getName());
  98. // }
  99. // },2,3,TimeUnit.SECONDS);//初始化延迟2s开始执行,每隔3s重新执行一次任务。
  100. //上面如果当前时间是10点,设置initialDelay:2,period:3,unit:小时
  101. //第一次:10:00 + 2 = 12:00
  102. //第二次:10:00 + 2 + 3 =15:00
  103. //第三次:10:00 + 2 + 2*3 =18:00
  104. //第n次:10:00 + 2 + n*3...
  105. //法三:scheduleWithFixedDelay(...):按指定频率间隔执行某个任务
  106. // 参数1:为执行的任务;参数2:为初始延迟时间;参数3:后续任务的延迟执行时间;参数4:为延迟执行的时间单位:
  107. // 解释:
  108. // 第一次调度开始时间点=当前时间+initialDelay
  109. // 下一次调度开始时间点=上一次task完成时间点+delay
  110. // scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
  111. // @Override
  112. // public void run() {
  113. // Date d = new Date();
  114. // SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  115. // System.out.println(df.format(d));
  116. // System.out.println("执行线程:"+Thread.currentThread().getName());
  117. // }
  118. // },5,3,TimeUnit.SECONDS);//初始化延迟5s开始执行,后续任务开始时间是在其前一个任务结束后延迟2s重新执行。
  119. }
  120. //方式四:newSingleThreadExecutor:创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,
  121. // 保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
  122. private static void newSingleThreadExecutor() {
  123. ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
  124. for (int i = 0; i < 10; i++) {
  125. final int index=i;
  126. singleThreadExecutor.execute(new Runnable() {
  127. @Override
  128. public void run() {
  129. try {
  130. System.out.println("任务:"+index);
  131. System.out.println("执行线程:"+Thread.currentThread().getName());
  132. Thread.sleep(2000);
  133. } catch (InterruptedException e) {
  134. // TODO Auto-generated catch block
  135. e.printStackTrace();
  136. }
  137. }
  138. });
  139. }
  140. }
  141. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/246498
推荐阅读
相关标签
  

闽ICP备14008679号