zoukankan      html  css  js  c++  java
  • (七)多线程:线程池

     系统启动一个新线程的成本时比较高的,因为它涉及于操作系统交涉。在这种情形下,使用线程池可以很好地提高性能,尤其是当程序中需要创建大量生存期限很短的线程时,更应该考虑使用线程池。
     与数据库连接池类似的是,线程池在启动时即创建大量空闲的线程,程序将一个Runnable对像或Callable对象传给线程池,线程池就会启动一个线程来执行他们的run()或call()方法,放run()或call()方法执行结束后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待执行下一个Runnable对象的run()或call()方法。
     除此之外,使用线程池可以有效地控制系统中并发线程的数量,当系统中包含大量并发线程时,会导致系统性能急剧下降,甚至导致JVM崩溃,而线程池的最大线程数参数可以控制系统中并发线程数不超过此数。

    1.Java8改进的线程池

     在Java5以前,开发者必须手动实现自己的线程池;从Java5开始,Java内建支持线程池。Java5新增了一个Executors工厂类来产生线程池,该工厂类包含了如下几个静态工厂方法来创建线程池。

    • newCachedThreadPool():创建一个具有缓存功能的线程池,系统根据需要创建线程,这些线程将会被缓存在线程池中。
    • newFixedThreadPool(int nThreads):创建一个可重用的,具有固定线程数的线程池。
    • newSingleThreadExecutor():创建一个只有单线程的线程池,它相当于调用newFixedThreadPool()方法时传入参数为1。
    • newScheduledThreadPool(int corePoolSize):创建具有指定线程数的线程池,它可以在指定延迟后执行线程任务。corePoolSize指池中所保存的线程数,即使线程是空闲的也被保存在线程池内。
    • newSingleThreadScheduledExecutor():创建只有一个线程的线程池,它可以在指定延迟后执行线程任务。
    • ExecutorService newWorkStealingPool(int parallelism):创建持有足够的线程的线程池来支持给定的并行级别,该方法还会使用多个队列来减少竞争。
    • ExecutorService newWorkStealingPool():该方法是前一个方法的简化版本。如果当前机器有四个CPU,则目标并行级别被设置为4,也就是相当于前一个方法传入4作为参数。

     上面7个方法中前三个方法返回ExecutorService对象,该对象代表一个线程池,它可以执行Runnable对象或Callable对象所代表的线程;而中间两个方法返回一个ScheduledExecutorSerivce线程池,它是ExecutorService的子类,它可以在指定延迟后执行线程任务;最后两个方法则是Java8新增的,这两个方法可以充分利用多CPU并行能力。这两个方法生成的work stealing池,都相当于后台线程池,如果所有的前台线程都死亡了,work stealing 池中的线程会自动死亡。
     由于目前计算机硬件的发展日新月异,即使普通用户的电脑通常也都是多核CPU,因此Java8在线程支持上也增加了利用多CPU并行的能力,这样可以更好地发挥底层硬件的性能。

     ExecutorService代表尽快执行线程的线程池(只要线程池中有空闲线程,就立即执行线程任务),程序只要将一个Runnable对象或Callable对象(代表线程任务)提交给该线程池,该线程池会尽快执行该任务。ExecutorService里提供了如下三个方法。

    • Future<?> submit(Runnable task):将一个Runnable对象提交给指定的线程池,线程池将在有空闲线程时执行Runnable对象代表的任务。其中Future对象代表Runnable任务的返回值——但run()方法没有返回值,所以Future对象将在run()方法执行结束后返回null(),但可以调用Future的isDone(),isCancelled()方法来获得Runnable对象的执行状态。
    • Future submit(Runnable task,T result):将一个Runnable对象提交给指定的线程池,线程池将在有空闲线程时执行Runnable对象代表的任务,其中result显式指定线程执行结束后返回值,所以Future对象将在run()方法执行结束后返回result。
    • Future submit(Callable task):将一个Callable对象提交给指定的线程池,线程池将在有空闲线程时执行Callable对象代表的任务。其中Future代表Callable对象里call()方法的返回值。

     ScheduledExecutorService代表可在指定延迟后或周期性地执行线程任务的线程池,它提供如下4个方法。

    • ScheduledFuture schedule(Callable callable,long delay,TimeUnit unit):指定callable任务将在delay延迟后执行。
    • ScheduledFuture<?> schedule(Runnable command,long delay,TimeUnit unit):指定command任务将在delay延迟后执行。
    • ScheduledFuture scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit):指定command任务将在delay延迟后执行,而且以设定频率重复执行。也就是说在initialDelay 后开始执行,依次在 initialDelay+period,initialDelay+2*period···处重复执行,依此类推。
    • ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit):创建并执行一个在给定初始延迟后首次启动的定期操作,随后在每一次执行终止和下一次执行开始之间都存在给定的延迟。如果任务在任一次执行时遇到异常,就会取消后续执行;否则通过程序来显式取消或终止该任务。、

     用完一个线程池后,应该调用该线程池的shutdown()方法,该方法将启动线程池的关闭序列,调用shutdown()方法后的线程池不再接受新任务,但会将以前所有已提交任务执行完成。当线程池中所有任务执行完成后,池中的所有线程都会死亡;另外也可以调用线程池的shutdownNow()方法来关闭线程池,改方法试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表。
    使用线程池来执行线程任务的步骤如下:

    • 调用Executors类的静态工厂方法来创建一个ExecutorService对象,该对象代表一个线程池。
    • 创建Runnable实现类或Callable实现类的实例,作为线程执行任务。
    • 调用ExecutorService对象的submit()方法来提交Runnable实例或Callable实例。
    • 当不想提交任何任务时,调用ExecutorService对象的shutdown()方法来关闭线程池。

    示例代码:

    public class ThreadPoolTest {
    
       public static void main(String[] args) {
    
           //创建一个具有固定线程数的线程池
           ExecutorService executorService = Executors.newFixedThreadPool(6);
    
           Runnable target = () -> {
               for (int i = 0; i < 10; i++) {
                   System.out.println("t_name:" + Thread.currentThread().getName() + ",i:" + i);
               }
           };
    
           //向线程池中提交两个线程
           executorService.submit(target);
           executorService.submit(target);
           //关闭线程池
           executorService.shutdown();
       }
    }
    

    运行结果:

    t_name:pool-1-thread-1,i:0
    t_name:pool-1-thread-1,i:1
    t_name:pool-1-thread-1,i:2
    t_name:pool-1-thread-1,i:3
    t_name:pool-1-thread-1,i:4
    t_name:pool-1-thread-2,i:0
    t_name:pool-1-thread-1,i:5
    t_name:pool-1-thread-1,i:6
    t_name:pool-1-thread-2,i:1
    t_name:pool-1-thread-1,i:7
    t_name:pool-1-thread-1,i:8
    t_name:pool-1-thread-2,i:2
    t_name:pool-1-thread-1,i:9
    t_name:pool-1-thread-2,i:3
    t_name:pool-1-thread-2,i:4
    t_name:pool-1-thread-2,i:5
    t_name:pool-1-thread-2,i:6
    t_name:pool-1-thread-2,i:7
    t_name:pool-1-thread-2,i:8
    t_name:pool-1-thread-2,i:9
    

    注意:创建了Runnable实现类之后程序没有直接创建线程,启动线程来执行该Runnable任务,而是通过线程池来执行该任务。

    2.Java8增强的ForkJoinPool

     为了充分利用CPU,多核CPU的性能优势,计算机软件系统可以充分“挖掘”每个CPU的计算能力,绝不能让某个CPU处于“空闲”状态。为了充分利用多CPU,多核CPU的优势,可以考虑把一个任务拆分成多个“小任务”,把多个“小任务”放在多个处理器核心上并行执行;当多个“小任务”执行完成之后,再将这些执行结果合并起来即可。
     Java7提供了ForkJoinPool来支持将一个任务拆分成多个“小任务”并行计算,再把多个“小任务”的结果合并成总的计算结果。ForkJoinPool是ExecutorService的实现类,因此是一种特殊的线程池。ForkJoinPool提供了如下两个常用的构造器。

    • ForkJoinPool(int parallelism):创建一个包含parallelism个并行线程的ForkJoinPool。
    • ForkJoinPool():以Runtime.availableProcessors()方法的返回值作为parallelism参数来创建ForkJoinPool。

     Java8进一步扩展了ForkJoinPool的功能,Java8为ForkJoinPool增加了通用池功能。ForkJoinPool类通过如下两个静态方法提供通用池功能。

    • ForkJoinPool commonPool():改方法返回一个通用池,通用池的运行状态不会受shutdown()或shutdownNow()方法的影响。当然,如果程序直接执行System.exit(0);来终止虚拟机,通用池以及通用池中正在执行的任务都将会被自动终止。
    • int getCommonPoolParallelism():该方法返回通用池的并行级别。

     创建了ForkJoinPool实例后,就可以调用ForkJoinPool的submit(ForkJoinTask task)或invoke(ForkJoinTask task)方法来执行指定任务了,其中ForkJoinTask代表一个可以并行,合并的任务。ForkJoinTask 是一个抽象类,它还有两个抽象子类:RecursiveAction和RecursiveTask。其中RecursiveTask代表有返回值的任务,而RecursiveAction代表没有返回值的任务。

    下面以执行没有返回值的“大任务”(简单地打印0-300的数值)为例,程序将一个“大任务”拆分成多个“小任务”,并将任务交给ForkJoinPool来执行:

    public class PrintTask extends RecursiveAction {
    
       //每个“小任务最多打印50个数”
       private static final int THRESHOLD = 50;
    
       private int start;
    
       private int end;
    
       public PrintTask(int start, int end) {
           this.start = start;
           this.end = end;
       }
    
       @Override
       protected void compute() {
           if (end - start < THRESHOLD) {
               for (int i = start; i < end; i++) {
                   System.out.println(Thread.currentThread().getName() + "的i值:" + i);
               }
           } else {
               //当end与start之间的差值大于THRESHOLD,即要打印的数超过50个时
               //将大任务分解成两个“小任务”
               int middle = (start + end) / 2;
               PrintTask left = new PrintTask(start, middle);
               PrintTask right = new PrintTask(middle, end);
               //并行执行两个“小任务”
               left.fork();
               right.fork();
           }
       }
    }
    
    public class ForkJoinPoolTest {
    
       public static void main(String[] args) throws InterruptedException {
    
           ForkJoinPool pool = new ForkJoinPool();
    
           //提交可分解的PrintTask任务
           pool.submit(new PrintTask(1, 300));
           pool.awaitTermination(2, TimeUnit.SECONDS);
           //关闭线程池
           pool.shutdown();
       }
    }
    

    运行结果:

    ForkJoinPool-1-worker-2的i值:112
    ForkJoinPool-1-worker-2的i值:113
    ForkJoinPool-1-worker-2的i值:114
    ForkJoinPool-1-worker-4的i值:38
    ForkJoinPool-1-worker-6的i值:150
    ForkJoinPool-1-worker-1的i值:262
    ForkJoinPool-1-worker-3的i值:187
    ForkJoinPool-1-worker-1的i值:263
    ForkJoinPool-1-worker-6的i值:151
    ForkJoinPool-1-worker-6的i值:152
    ForkJoinPool-1-worker-4的i值:39
    ForkJoinPool-1-worker-2的i值:115
    ForkJoinPool-1-worker-4的i值:40
    ForkJoinPool-1-worker-6的i值:153
    ForkJoinPool-1-worker-0的i值:1
    ForkJoinPool-1-worker-5的i值:75
    ForkJoinPool-1-worker-1的i值:264
    ForkJoinPool-1-worker-7的i值:225
    ForkJoinPool-1-worker-3的i值:188
    ForkJoinPool-1-worker-7的i值:226
    ForkJoinPool-1-worker-1的i值:265
    ForkJoinPool-1-worker-5的i值:76
    ForkJoinPool-1-worker-0的i值:2
    ForkJoinPool-1-worker-0的i值:3
    ForkJoinPool-1-worker-6的i值:154
    ForkJoinPool-1-worker-4的i值:41
    ForkJoinPool-1-worker-2的i值:116
    ForkJoinPool-1-worker-2的i值:117
    ForkJoinPool-1-worker-2的i值:118
    ForkJoinPool-1-worker-2的i值:119
    ForkJoinPool-1-worker-2的i值:120
    ForkJoinPool-1-worker-2的i值:121
    ForkJoinPool-1-worker-4的i值:42
    ForkJoinPool-1-worker-6的i值:155
    ForkJoinPool-1-worker-0的i值:4
    ForkJoinPool-1-worker-0的i值:5
    ForkJoinPool-1-worker-0的i值:6
    ForkJoinPool-1-worker-5的i值:77
    ForkJoinPool-1-worker-1的i值:266
    ForkJoinPool-1-worker-7的i值:227
    ForkJoinPool-1-worker-3的i值:189
    ForkJoinPool-1-worker-3的i值:190
    ForkJoinPool-1-worker-3的i值:191
    ForkJoinPool-1-worker-7的i值:228
    ForkJoinPool-1-worker-1的i值:267
    ForkJoinPool-1-worker-5的i值:78
    ForkJoinPool-1-worker-0的i值:7
    ForkJoinPool-1-worker-0的i值:8
    ForkJoinPool-1-worker-6的i值:156
    ForkJoinPool-1-worker-4的i值:43
    ForkJoinPool-1-worker-2的i值:122
    ForkJoinPool-1-worker-4的i值:44
    ForkJoinPool-1-worker-6的i值:157
    ForkJoinPool-1-worker-0的i值:9
    ForkJoinPool-1-worker-5的i值:79
    ForkJoinPool-1-worker-1的i值:268
    ForkJoinPool-1-worker-7的i值:229
    ForkJoinPool-1-worker-3的i值:192
    ForkJoinPool-1-worker-7的i值:230
    ForkJoinPool-1-worker-1的i值:269
    ForkJoinPool-1-worker-5的i值:80
    ForkJoinPool-1-worker-1的i值:270
    ForkJoinPool-1-worker-0的i值:10
    ForkJoinPool-1-worker-6的i值:158
    ForkJoinPool-1-worker-4的i值:45
    ForkJoinPool-1-worker-4的i值:46
    ForkJoinPool-1-worker-4的i值:47
    ForkJoinPool-1-worker-2的i值:123
    ForkJoinPool-1-worker-4的i值:48
    ForkJoinPool-1-worker-6的i值:159
    ForkJoinPool-1-worker-0的i值:11
    ForkJoinPool-1-worker-1的i值:271
    ForkJoinPool-1-worker-5的i值:81
    ForkJoinPool-1-worker-7的i值:231
    ForkJoinPool-1-worker-3的i值:193
    ForkJoinPool-1-worker-7的i值:232
    ForkJoinPool-1-worker-5的i值:82
    ForkJoinPool-1-worker-1的i值:272
    ForkJoinPool-1-worker-0的i值:12
    ForkJoinPool-1-worker-6的i值:160
    ForkJoinPool-1-worker-4的i值:49
    ForkJoinPool-1-worker-2的i值:124
    ForkJoinPool-1-worker-4的i值:50
    ForkJoinPool-1-worker-6的i值:161
    ForkJoinPool-1-worker-0的i值:13
    ForkJoinPool-1-worker-1的i值:273
    ForkJoinPool-1-worker-5的i值:83
    ForkJoinPool-1-worker-7的i值:233
    ForkJoinPool-1-worker-7的i值:234
    ForkJoinPool-1-worker-7的i值:235
    ForkJoinPool-1-worker-7的i值:236
    ForkJoinPool-1-worker-7的i值:237
    ForkJoinPool-1-worker-7的i值:238
    ForkJoinPool-1-worker-7的i值:239
    ForkJoinPool-1-worker-7的i值:240
    ForkJoinPool-1-worker-7的i值:241
    ForkJoinPool-1-worker-3的i值:194
    ForkJoinPool-1-worker-7的i值:242
    ForkJoinPool-1-worker-7的i值:243
    ForkJoinPool-1-worker-7的i值:244
    ForkJoinPool-1-worker-7的i值:245
    ForkJoinPool-1-worker-7的i值:246
    ForkJoinPool-1-worker-7的i值:247
    ForkJoinPool-1-worker-5的i值:84
    ForkJoinPool-1-worker-1的i值:274
    ForkJoinPool-1-worker-0的i值:14
    ForkJoinPool-1-worker-6的i值:162
    ForkJoinPool-1-worker-4的i值:51
    ForkJoinPool-1-worker-2的i值:125
    ForkJoinPool-1-worker-2的i值:126
    ForkJoinPool-1-worker-2的i值:127
    ForkJoinPool-1-worker-2的i值:128
    ForkJoinPool-1-worker-2的i值:129
    ForkJoinPool-1-worker-4的i值:52
    ForkJoinPool-1-worker-6的i值:163
    ForkJoinPool-1-worker-6的i值:164
    ForkJoinPool-1-worker-6的i值:165
    ForkJoinPool-1-worker-6的i值:166
    ForkJoinPool-1-worker-6的i值:167
    ForkJoinPool-1-worker-6的i值:168
    ForkJoinPool-1-worker-0的i值:15
    ForkJoinPool-1-worker-1的i值:275
    ForkJoinPool-1-worker-5的i值:85
    ForkJoinPool-1-worker-7的i值:248
    ForkJoinPool-1-worker-7的i值:249
    ForkJoinPool-1-worker-7的i值:250
    ForkJoinPool-1-worker-7的i值:251
    ForkJoinPool-1-worker-7的i值:252
    ForkJoinPool-1-worker-3的i值:195
    ForkJoinPool-1-worker-7的i值:253
    ForkJoinPool-1-worker-5的i值:86
    ForkJoinPool-1-worker-1的i值:276
    ForkJoinPool-1-worker-0的i值:16
    ForkJoinPool-1-worker-6的i值:169
    ForkJoinPool-1-worker-4的i值:53
    ForkJoinPool-1-worker-2的i值:130
    ForkJoinPool-1-worker-4的i值:54
    ForkJoinPool-1-worker-6的i值:170
    ForkJoinPool-1-worker-0的i值:17
    ForkJoinPool-1-worker-1的i值:277
    ForkJoinPool-1-worker-5的i值:87
    ForkJoinPool-1-worker-7的i值:254
    ForkJoinPool-1-worker-3的i值:196
    ForkJoinPool-1-worker-7的i值:255
    ForkJoinPool-1-worker-5的i值:88
    ForkJoinPool-1-worker-1的i值:278
    ForkJoinPool-1-worker-0的i值:18
    ForkJoinPool-1-worker-6的i值:171
    ForkJoinPool-1-worker-4的i值:55
    ForkJoinPool-1-worker-2的i值:131
    ForkJoinPool-1-worker-4的i值:56
    ForkJoinPool-1-worker-6的i值:172
    ForkJoinPool-1-worker-0的i值:19
    ForkJoinPool-1-worker-1的i值:279
    ForkJoinPool-1-worker-5的i值:89
    ForkJoinPool-1-worker-7的i值:256
    ForkJoinPool-1-worker-7的i值:257
    ForkJoinPool-1-worker-7的i值:258
    ForkJoinPool-1-worker-7的i值:259
    ForkJoinPool-1-worker-7的i值:260
    ForkJoinPool-1-worker-7的i值:261
    ForkJoinPool-1-worker-3的i值:197
    ForkJoinPool-1-worker-5的i值:90
    ForkJoinPool-1-worker-1的i值:280
    ForkJoinPool-1-worker-1的i值:281
    ForkJoinPool-1-worker-0的i值:20
    ForkJoinPool-1-worker-0的i值:21
    ForkJoinPool-1-worker-0的i值:22
    ForkJoinPool-1-worker-0的i值:23
    ForkJoinPool-1-worker-0的i值:24
    ForkJoinPool-1-worker-0的i值:25
    ForkJoinPool-1-worker-0的i值:26
    ForkJoinPool-1-worker-0的i值:27
    ForkJoinPool-1-worker-0的i值:28
    ForkJoinPool-1-worker-0的i值:29
    ForkJoinPool-1-worker-0的i值:30
    ForkJoinPool-1-worker-6的i值:173
    ForkJoinPool-1-worker-4的i值:57
    ForkJoinPool-1-worker-2的i值:132
    ForkJoinPool-1-worker-2的i值:133
    ForkJoinPool-1-worker-2的i值:134
    ForkJoinPool-1-worker-2的i值:135
    ForkJoinPool-1-worker-2的i值:136
    ForkJoinPool-1-worker-2的i值:137
    ForkJoinPool-1-worker-2的i值:138
    ForkJoinPool-1-worker-2的i值:139
    ForkJoinPool-1-worker-2的i值:140
    ForkJoinPool-1-worker-4的i值:58
    ForkJoinPool-1-worker-6的i值:174
    ForkJoinPool-1-worker-0的i值:31
    ForkJoinPool-1-worker-0的i值:32
    ForkJoinPool-1-worker-0的i值:33
    ForkJoinPool-1-worker-1的i值:282
    ForkJoinPool-1-worker-1的i值:283
    ForkJoinPool-1-worker-1的i值:284
    ForkJoinPool-1-worker-1的i值:285
    ForkJoinPool-1-worker-5的i值:91
    ForkJoinPool-1-worker-3的i值:198
    ForkJoinPool-1-worker-3的i值:199
    ForkJoinPool-1-worker-3的i值:200
    ForkJoinPool-1-worker-3的i值:201
    ForkJoinPool-1-worker-3的i值:202
    ForkJoinPool-1-worker-3的i值:203
    ForkJoinPool-1-worker-3的i值:204
    ForkJoinPool-1-worker-3的i值:205
    ForkJoinPool-1-worker-3的i值:206
    ForkJoinPool-1-worker-3的i值:207
    ForkJoinPool-1-worker-3的i值:208
    ForkJoinPool-1-worker-3的i值:209
    ForkJoinPool-1-worker-3的i值:210
    ForkJoinPool-1-worker-3的i值:211
    ForkJoinPool-1-worker-5的i值:92
    ForkJoinPool-1-worker-5的i值:93
    ForkJoinPool-1-worker-1的i值:286
    ForkJoinPool-1-worker-0的i值:34
    ForkJoinPool-1-worker-6的i值:175
    ForkJoinPool-1-worker-4的i值:59
    ForkJoinPool-1-worker-2的i值:141
    ForkJoinPool-1-worker-4的i值:60
    ForkJoinPool-1-worker-6的i值:176
    ForkJoinPool-1-worker-0的i值:35
    ForkJoinPool-1-worker-1的i值:287
    ForkJoinPool-1-worker-5的i值:94
    ForkJoinPool-1-worker-5的i值:95
    ForkJoinPool-1-worker-5的i值:96
    ForkJoinPool-1-worker-5的i值:97
    ForkJoinPool-1-worker-3的i值:212
    ForkJoinPool-1-worker-5的i值:98
    ForkJoinPool-1-worker-1的i值:288
    ForkJoinPool-1-worker-1的i值:289
    ForkJoinPool-1-worker-1的i值:290
    ForkJoinPool-1-worker-1的i值:291
    ForkJoinPool-1-worker-1的i值:292
    ForkJoinPool-1-worker-1的i值:293
    ForkJoinPool-1-worker-0的i值:36
    ForkJoinPool-1-worker-6的i值:177
    ForkJoinPool-1-worker-6的i值:178
    ForkJoinPool-1-worker-6的i值:179
    ForkJoinPool-1-worker-6的i值:180
    ForkJoinPool-1-worker-6的i值:181
    ForkJoinPool-1-worker-4的i值:61
    ForkJoinPool-1-worker-2的i值:142
    ForkJoinPool-1-worker-4的i值:62
    ForkJoinPool-1-worker-6的i值:182
    ForkJoinPool-1-worker-0的i值:37
    ForkJoinPool-1-worker-1的i值:294
    ForkJoinPool-1-worker-1的i值:295
    ForkJoinPool-1-worker-1的i值:296
    ForkJoinPool-1-worker-1的i值:297
    ForkJoinPool-1-worker-1的i值:298
    ForkJoinPool-1-worker-1的i值:299
    ForkJoinPool-1-worker-5的i值:99
    ForkJoinPool-1-worker-5的i值:100
    ForkJoinPool-1-worker-5的i值:101
    ForkJoinPool-1-worker-5的i值:102
    ForkJoinPool-1-worker-5的i值:103
    ForkJoinPool-1-worker-3的i值:213
    ForkJoinPool-1-worker-3的i值:214
    ForkJoinPool-1-worker-3的i值:215
    ForkJoinPool-1-worker-3的i值:216
    ForkJoinPool-1-worker-5的i值:104
    ForkJoinPool-1-worker-6的i值:183
    ForkJoinPool-1-worker-6的i值:184
    ForkJoinPool-1-worker-6的i值:185
    ForkJoinPool-1-worker-6的i值:186
    ForkJoinPool-1-worker-4的i值:63
    ForkJoinPool-1-worker-2的i值:143
    ForkJoinPool-1-worker-2的i值:144
    ForkJoinPool-1-worker-4的i值:64
    ForkJoinPool-1-worker-5的i值:105
    ForkJoinPool-1-worker-5的i值:106
    ForkJoinPool-1-worker-5的i值:107
    ForkJoinPool-1-worker-5的i值:108
    ForkJoinPool-1-worker-3的i值:217
    ForkJoinPool-1-worker-5的i值:109
    ForkJoinPool-1-worker-5的i值:110
    ForkJoinPool-1-worker-5的i值:111
    ForkJoinPool-1-worker-4的i值:65
    ForkJoinPool-1-worker-2的i值:145
    ForkJoinPool-1-worker-2的i值:146
    ForkJoinPool-1-worker-2的i值:147
    ForkJoinPool-1-worker-2的i值:148
    ForkJoinPool-1-worker-2的i值:149
    ForkJoinPool-1-worker-4的i值:66
    ForkJoinPool-1-worker-4的i值:67
    ForkJoinPool-1-worker-3的i值:218
    ForkJoinPool-1-worker-4的i值:68
    ForkJoinPool-1-worker-3的i值:219
    ForkJoinPool-1-worker-4的i值:69
    ForkJoinPool-1-worker-3的i值:220
    ForkJoinPool-1-worker-4的i值:70
    ForkJoinPool-1-worker-3的i值:221
    ForkJoinPool-1-worker-3的i值:222
    ForkJoinPool-1-worker-3的i值:223
    ForkJoinPool-1-worker-4的i值:71
    ForkJoinPool-1-worker-3的i值:224
    ForkJoinPool-1-worker-4的i值:72
    ForkJoinPool-1-worker-4的i值:73
    ForkJoinPool-1-worker-4的i值:74
    

     如果大任务时有返回值的任务,则可以让任务继承RecursiveTask<T>,其中泛型参数T就代表了改任务的返回值类型。代码示例省略。

    文章内容均取自《疯狂Java讲义-李刚》一书中多线程章节。截取重要知识点作为笔记记录,方便自己回顾。

  • 相关阅读:
    Python基础知识2-内置数据结构(上)
    vs code的快捷方式
    vs code配置
    vs code安装
    web浏览器兼容问题
    js正則表達式
    MVC MVP MVVM
    vue-cli(vue脚手架)
    web攻擊
    web前端面試題
  • 原文地址:https://www.cnblogs.com/everyingo/p/12824997.html
Copyright © 2011-2022 走看看