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讲义-李刚》一书中多线程章节。截取重要知识点作为笔记记录,方便自己回顾。

  • 相关阅读:
    ZOJ Problem Set–2417 Lowest Bit
    ZOJ Problem Set–1402 Magnificent Meatballs
    ZOJ Problem Set–1292 Integer Inquiry
    ZOJ Problem Set–1109 Language of FatMouse
    ZOJ Problem Set–1295 Reverse Text
    ZOJ Problem Set–1712 Skew Binary
    ZOJ Problem Set–1151 Word Reversal
    ZOJ Problem Set–1494 Climbing Worm
    ZOJ Problem Set–1251 Box of Bricks
    ZOJ Problem Set–1205 Martian Addition
  • 原文地址:https://www.cnblogs.com/everyingo/p/12824997.html
Copyright © 2011-2022 走看看