Java5线程池潜规则研究

简介:
为了研究Java5的线程池任务的执行过程,写了小例子。
为什么要研究呢,因为Java没有告诉我们什么时候是对的,什么时候是做的,面对冷冰冰的API说明,往往会迷茫。通过实例来验证才是王道!
 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.TimeUnit; 

/** 
* 线程池的测试 

* @author leizhimin 2009-7-7 14:15:43 
*/
 
public  class DownTask  implements Runnable { 
         private  int x;             //线程编号 

         public DownTask( int x) { 
                 this.x = x; 
        } 

         public  void run() { 
                System.out.println(x +  " thread doing something!"); 
                 try { 
                        TimeUnit.SECONDS.sleep(5L); 
                        System.out.println( "第" + x +  "个线程休息完毕"); 
                }  catch (InterruptedException e) { 
                        e.printStackTrace(); 
                } 
        } 


class FixedThreadPool { 
         public  static  void main(String[] args) { 
                ExecutorService exec = Executors.newFixedThreadPool(2); 
                 for ( int i = 0; i < 50; i++) { 
                        exec.execute( new DownTask(i)); 
                } 
        } 
}
 
执行结果:
0 thread doing something! 
1 thread doing something! 
第1个线程休息完毕 
第0个线程休息完毕 
2 thread doing something! 
3 thread doing something! 
第2个线程休息完毕 
第3个线程休息完毕 
4 thread doing something! 
5 thread doing something! 
第4个线程休息完毕 
第5个线程休息完毕 
6 thread doing something! 
7 thread doing something! 
第6个线程休息完毕 
8 thread doing something! 
第7个线程休息完毕 
9 thread doing something! 
第9个线程休息完毕 
第8个线程休息完毕 
10 thread doing something! 
11 thread doing something! 
第10个线程休息完毕 
第11个线程休息完毕 
12 thread doing something! 
13 thread doing something! 
第12个线程休息完毕 
第13个线程休息完毕 
14 thread doing something! 
15 thread doing something! 
第15个线程休息完毕 
第14个线程休息完毕 
16 thread doing something! 
17 thread doing something! 
......
 
1、将上面的代码改为
        ExecutorService exec = Executors.newCachedThreadPool();
 
执行结果:
1 thread doing something! 
2 thread doing something! 
0 thread doing something! 
6 thread doing something! 
4 thread doing something! 
3 thread doing something! 
5 thread doing something! 
8 thread doing something! 
10 thread doing something! 
12 thread doing something! 
7 thread doing something! 
14 thread doing something! 
9 thread doing something! 
19 thread doing something! 
11 thread doing something! 
13 thread doing something! 
18 thread doing something! 
15 thread doing something! 
17 thread doing something! 
16 thread doing something! 
20 thread doing something! 
22 thread doing something! 
24 thread doing something! 
21 thread doing something! 
26 thread doing something! 
23 thread doing something! 
27 thread doing something! 
25 thread doing something! 
28 thread doing something! 
29 thread doing something! 
30 thread doing something! 
31 thread doing something! 
32 thread doing something! 
33 thread doing something! 
34 thread doing something! 
35 thread doing something! 
36 thread doing something! 
37 thread doing something! 
38 thread doing something! 
39 thread doing something! 
40 thread doing something! 
42 thread doing something! 
44 thread doing something! 
43 thread doing something! 
41 thread doing something! 
45 thread doing something! 
47 thread doing something! 
46 thread doing something! 
48 thread doing something! 
49 thread doing something! 
第2个线程休息完毕 
第3个线程休息完毕 
第5个线程休息完毕 
第0个线程休息完毕 
第4个线程休息完毕 
第1个线程休息完毕 
第10个线程休息完毕 
第8个线程休息完毕 
第6个线程休息完毕 
第12个线程休息完毕 
第7个线程休息完毕 
第14个线程休息完毕 
第9个线程休息完毕 
第19个线程休息完毕 
第11个线程休息完毕 
第18个线程休息完毕 
第13个线程休息完毕 
第15个线程休息完毕 
第17个线程休息完毕 
第16个线程休息完毕 
第27个线程休息完毕 
第21个线程休息完毕 
第20个线程休息完毕 
第24个线程休息完毕 
第26个线程休息完毕 
第28个线程休息完毕 
第25个线程休息完毕 
第29个线程休息完毕 
第23个线程休息完毕 
第22个线程休息完毕 
第34个线程休息完毕 
第33个线程休息完毕 
第30个线程休息完毕 
第32个线程休息完毕 
第31个线程休息完毕 
第35个线程休息完毕 
第36个线程休息完毕 
第37个线程休息完毕 
第38个线程休息完毕 
第40个线程休息完毕 
第42个线程休息完毕 
第47个线程休息完毕 
第46个线程休息完毕 
第43个线程休息完毕 
第45个线程休息完毕 
第49个线程休息完毕 
第44个线程休息完毕 
第39个线程休息完毕 
第41个线程休息完毕 
第48个线程休息完毕 

Process finished with exit code 0
 
太恐怖了,一次性分配50个线程,如果换成100、5000、8000会如何呢?(代码中将“休息”二字改为“执行”二字了。)
第7996个线程执行完毕 
第7989个线程执行完毕 
第7990个线程执行完毕 
第7991个线程执行完毕 
第7993个线程执行完毕 
第7997个线程执行完毕 
第7998个线程执行完毕
 
看来没有固定线程数的池子并没有把系统跑死啊。
 
2、看下面的这个重量级线程例子
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.TimeUnit; 

/** 
* 线程池的测试 

* @author leizhimin 2009-7-7 14:15:43 
*/
 
public  class DownTask  implements Runnable { 
         private  int x;             //线程编号 

         public DownTask( int x) { 
                 this.x = x; 
        } 

         public  void run() { 
                System.out.println(x +  " thread doing something!"); 
                 //一个非常耗时的任务 
                 for( int i=0;i<999999999L;i++); 
                System.out.println( "第" + x +  "个线程执行完毕"); 
        } 


class TestThreadPool { 
         public  static  void main(String[] args) { 
//                ExecutorService exec = Executors.newFixedThreadPool(2); 
                ExecutorService exec = Executors.newCachedThreadPool(); 
                 for ( int i = 0; i < 100; i++) { 
                        exec.execute( new DownTask(i)); 
                } 
        } 
}
 
跑吧,这100个线程能讲双核2G内存的机器搞的三分钟多没响应,不信的话你试试看!
 
如果将线程池换成固定大小的看看会发生什么:
 
结果:
1 thread doing something! 
0 thread doing something! 
第0个线程执行完毕 
2 thread doing something! 
第1个线程执行完毕 
3 thread doing something! 
第2个线程执行完毕 
4 thread doing something! 
第3个线程执行完毕 
5 thread doing something! 
第4个线程执行完毕 
6 thread doing something! 
第5个线程执行完毕 
7 thread doing something! 
第6个线程执行完毕 
......
 
并没有觉得很慢,程序坚持了一会儿就把所有任务跑完了。。。
 
这个结果很令人震撼吧。一万个线程没搞挂系统,100个线程把系统搞挂了。
 
3、注意观察线程池关闭的方法
 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 

/** 
* 线程池的测试 

* @author leizhimin 2009-7-7 14:15:43 
*/
 
public  class DownTask  implements Runnable { 
         private  int x;             //线程编号 

         public DownTask( int x) { 
                 this.x = x; 
        } 

         public  void run() { 
                System.out.println(x +  " thread doing something!"); 
                System.out.println( "第" + x +  "个线程执行完毕"); 
        } 


class TestThreadPool { 
         public  static  void main(String[] args)  throws InterruptedException { 
                ExecutorService exec = Executors.newFixedThreadPool(2); 
                 for ( int i = 0; i < 5; i++) { 
                        exec.execute( new DownTask(i)); 
                } 
                 exec.shutdown(); 
        } 
}
 
上面代码执行结果:
0 thread doing something! 
第0个线程执行完毕 
2 thread doing something! 
第2个线程执行完毕 
3 thread doing something! 
第3个线程执行完毕 
4 thread doing something! 
第4个线程执行完毕 
1 thread doing something! 
第1个线程执行完毕 

Process finished with exit code 0
 
将代码中的exec.shutdown();注释掉,会发生什么呢?-----程序会一直等待任务入池,而不退出。
0 thread doing something! 
第0个线程执行完毕 
2 thread doing something! 
第2个线程执行完毕 
3 thread doing something! 
第3个线程执行完毕 
4 thread doing something! 
第4个线程执行完毕 
1 thread doing something! 
第1个线程执行完毕 
 
 
经过总结,得出几条经验:
1、轻量级任务(Runnable对象、Thread对象、Callable对象)可以选择不固定大小的线程池来执行,或者任务数量很少,也可以选择。
 
2、重量级的线程,每个线程耗时、耗资源都很大,那么就应该考虑固定大小的线程池了。
 
3、线程池任务的添加执行是JVM内部机制控制的,你不用担心循环添加很多任务会把固定线程池的池子撑破。因为我见过有人还为控制这个问题煞费苦心呢!呵呵:)
 
4、线程池初始化数量是根据系统的性能等要求来测试决定的,不是凭空想象。
 
5、另外,多线程编程中,要注意释放一些不要的资源,以便重新利用。像那个巨大空循环,会耗费大量的cpu和内存,以致系统没能力去做别的事情了,如果for语句便利一个庞大的集合,遍历完成后,最好可以讲null赋给集合以便尽快被垃圾回收器回收掉。
 
6、线程池给多线程编程带来了极大的便利,但这个API本身描述很模糊。在使用线程池的时候,一定要注意关闭池的策略。如果忘记关闭了,程序会一直等待。


本文转自 leizhimin 51CTO博客,原文链接:http://blog.51cto.com/lavasoft/174964,如需转载请自行联系原作者
相关文章
|
7天前
|
存储 Java 数据库连接
java多线程之线程通信
java多线程之线程通信
|
7天前
|
安全 Java 开发者
深入理解Java并发编程:线程安全与性能优化
【4月更文挑战第9天】本文将深入探讨Java并发编程的核心概念,包括线程安全和性能优化。我们将详细解析Java中的同步机制,包括synchronized关键字、Lock接口以及并发集合等,并探讨它们如何影响程序的性能。此外,我们还将讨论Java内存模型,以及它如何影响并发程序的行为。最后,我们将提供一些实用的并发编程技巧和最佳实践,帮助开发者编写出既线程安全又高效的Java程序。
20 3
|
10天前
|
设计模式 安全 Java
Java并发编程实战:使用synchronized关键字实现线程安全
【4月更文挑战第6天】Java中的`synchronized`关键字用于处理多线程并发,确保共享资源的线程安全。它可以修饰方法或代码块,实现互斥访问。当用于方法时,锁定对象实例或类对象;用于代码块时,锁定指定对象。过度使用可能导致性能问题,应注意避免锁持有时间过长、死锁,并考虑使用`java.util.concurrent`包中的高级工具。正确理解和使用`synchronized`是编写线程安全程序的关键。
|
8天前
|
Java
Java 并发编程:深入理解线程池
【4月更文挑战第8天】本文将深入探讨 Java 中的线程池技术,包括其工作原理、优势以及如何使用。线程池是 Java 并发编程的重要工具,它可以有效地管理和控制线程的执行,提高系统性能。通过本文的学习,读者将对线程池有更深入的理解,并能在实际开发中灵活运用。
|
7天前
|
算法 Java 开发者
Java中的多线程编程:概念、实现与性能优化
【4月更文挑战第9天】在Java编程中,多线程是一种强大的工具,它允许开发者创建并发执行的程序,提高系统的响应性和吞吐量。本文将深入探讨Java多线程的核心概念,包括线程的生命周期、线程同步机制以及线程池的使用。接着,我们将展示如何通过继承Thread类和实现Runnable接口来创建线程,并讨论各自的优缺点。此外,文章还将介绍高级主题,如死锁的预防、避免和检测,以及如何使用并发集合和原子变量来提高多线程程序的性能和安全性。最后,我们将提供一些实用的性能优化技巧,帮助开发者编写出更高效、更稳定的多线程应用程序。
|
5天前
|
安全 算法 Java
深入理解Java并发编程:线程安全与性能优化
【4月更文挑战第11天】 在Java中,高效的并发编程是提升应用性能和响应能力的关键。本文将探讨Java并发的核心概念,包括线程安全、锁机制、线程池以及并发集合等,同时提供实用的编程技巧和最佳实践,帮助开发者在保证线程安全的前提下,优化程序性能。我们将通过分析常见的并发问题,如竞态条件、死锁,以及如何利用现代Java并发工具来避免这些问题,从而构建更加健壮和高效的多线程应用程序。
|
9天前
|
Java
Java并发编程:深入理解线程池
【4月更文挑战第7天】在现代软件开发中,多线程编程已经成为一种不可或缺的技术。为了提高程序性能和资源利用率,Java提供了线程池这一强大工具。本文将深入探讨Java线程池的原理、使用方法以及如何根据实际需求定制线程池,帮助读者更好地理解和应用线程池技术。
15 0
|
1天前
|
设计模式 运维 安全
深入理解Java并发编程:线程安全与性能优化
【4月更文挑战第15天】在Java开发中,多线程编程是提升应用程序性能和响应能力的关键手段。然而,它伴随着诸多挑战,尤其是在保证线程安全的同时如何避免性能瓶颈。本文将探讨Java并发编程的核心概念,包括同步机制、锁优化、线程池使用以及并发集合等,旨在为开发者提供实用的线程安全策略和性能优化技巧。通过实例分析和最佳实践的分享,我们的目标是帮助读者构建既高效又可靠的多线程应用。
|
2天前
|
Java 程序员 编译器
Java中的线程同步与锁优化策略
【4月更文挑战第14天】在多线程编程中,线程同步是确保数据一致性和程序正确性的关键。Java提供了多种机制来实现线程同步,其中最常用的是synchronized关键字和Lock接口。本文将深入探讨Java中的线程同步问题,并分析如何通过锁优化策略提高程序性能。我们将首先介绍线程同步的基本概念,然后详细讨论synchronized和Lock的使用及优缺点,最后探讨一些锁优化技巧,如锁粗化、锁消除和读写锁等。
|
4天前
|
Java
探秘jstack:解决Java应用线程问题的利器
探秘jstack:解决Java应用线程问题的利器
14 1
探秘jstack:解决Java应用线程问题的利器