Java5线程池潜规则研究(3)

太恐怖了,一次性分配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本身描述很模糊。在使用线程池的时候,一定要注意关闭池的策略。如果忘记关闭了,程序会一直等待。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwsdwg.html