线程池的基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理。当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源。
在Java5之前,要实现一个线程池是相当有难度的,现在Java5为我们做好了一切,我们只需要按照提供的API来使用,即可享受线程池带来的极大便利。
Java5的线程池分好多种:具体的可以分为两类,固定尺寸的线程池、可变尺寸连接池。
Executor框架主要包含三个部分:
任务:包括Runnable和Callable,其中Runnable表示一个可以异步执行的任务,而Callable表示一个会产生结果的任务
任务的执行:包括Executor框架的核心接口Executor以及其子接口ExecutorService。在Executor框架中有两个关键类ThreadPoolExecutor和ScheduledThreadPoolExecutor实现了ExecutorService接口。
异步计算的结果:包括接口Future和其实现类FutureTask。
Executor接口(java.util.concurrent.Executor)
它是Executor的基础与核心,其定义如下:
public interface Executor {
void execute(Runnable command);
}
它包含了一个方法execute,参数为一个Runnable接口引用。
Executor接口将任务的提交与执行分离开来。
ThreadPoolExecutor类(java.util.concurrent.ThreadPoolExecutor)
它是线程池的核心实现类,用来执行被提交的任务。
它通常由工厂类Executors来创建,Executors可以创建SingleThreadExecutor,FixedThreadPool以及CachedThreadPool等不同的ThreadPoolExecutor。
一、固定大小的线程池,newFixedThreadPool:
满足了资源管理的需求,可以限制当前线程数量。适用于负载较重的服务器环境。
packageapp.executors;
importjava.util.concurrent.Executors;
importjava.util.concurrent.ExecutorService;
/**
* Java线程:线程池*
* @author 冯小卫
*/
publicclassTest {
publicstaticvoidmain(String[] args) {
// 创建一个可重用固定线程数的线程池
ExecutorService pool = Executors.newFixedThreadPool(5);
// 创建线程
Thread t1 =newMyThread();
Thread t2 =newMyThread();
Thread t3 =newMyThread();
Thread t4 =newMyThread();
Thread t5 =newMyThread();
// 将线程放入池中进行执行
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);
// 关闭线程池
pool.shutdown();
}
}
classMyThreadextendsThread {
@Override
publicvoidrun() {
System.out.println(Thread.currentThread().getName() +"正在执行。。。");
}
}
输出结果:
[html]view plaincopy
pool-1-thread-1正在执行。。。
pool-1-thread-3正在执行。。。
pool-1-thread-4正在执行。。。
pool-1-thread-2正在执行。。。
pool-1-thread-5正在执行。。。
改变ExecutorService pool = Executors.newFixedThreadPool(5)中的参数:ExecutorService pool = Executors.newFixedThreadPool(2),输出结果是:
[html]view plaincopy
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-2正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-2正在执行。。。
从以上结果可以看出,newFixedThreadPool的参数指定了可以运行的线程的最大数目,超过这个数目的线程加进去以后,不会运行。其次,加入线程池的线程属于托管状态,线程的运行不受加入顺序的影响。
二、单任务线程池,newSingleThreadExecutor:
仅仅是把上述代码中的ExecutorService pool = Executors.newFixedThreadPool(2)改为ExecutorService pool = Executors.newSingleThreadExecutor();
SingleThreadExecutor保证了任务执行的顺序,不会存在多线程活动。
输出结果:
[html]view plaincopy
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
可以看出,每次调用execute方法,其实最后都是调用了thread-1的run方法。
三、可变尺寸的线程池,newCachedThreadPool:
与上面的类似,只是改动下pool的创建方式:ExecutorService pool = Executors.newCachedThreadPool();
适用于执行很多短期异步任务的小程序,适用于负载较轻的服务器
输出:
[html]view plaincopy
pool-1-thread-1正在执行。。。
pool-1-thread-2正在执行。。。
pool-1-thread-4正在执行。。。
pool-1-thread-3正在执行。。。
pool-1-thread-5正在执行。。。
这种方式的特点是:可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。
四、延迟连接池,newScheduledThreadPool:
它可以在给定的延迟时间后执行命令,或者定期执行命令,它比Timer更强大更灵活。
ScheduledThreadPoolExecutor具有固定线程个数,适用于需要多个后台线程执行周期任务,并且为了满足资源管理需求而限制后台线程数量的场景
它适用于单个后台线程执行周期任务,并且保证顺序一致执行的场景。
[java]view plaincopy
packageapp.executors;
importjava.util.concurrent.Executors;
importjava.util.concurrent.ScheduledExecutorService;
importjava.util.concurrent.TimeUnit;
/**
* Java线程:线程池
*
* @author 冯小卫
*/
publicclassTest {
publicstaticvoidmain(String[] args) {
// 创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
// 创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口
Thread t1 =newMyThread();
Thread t2 =newMyThread();
Thread t3 =newMyThread();
// 将线程放入池中进行执行
pool.execute(t1);
// 使用延迟执行风格的方法
pool.schedule(t2,1000, TimeUnit.MILLISECONDS);
pool.schedule(t3,10, TimeUnit.MILLISECONDS);
// 关闭线程池
pool.shutdown();
}
}
classMyThreadextendsThread {
@Override
publicvoidrun() {
System.out.println(Thread.currentThread().getName() +"正在执行。。。");
}
}
读者可以尝试改变Executors.newScheduledThreadPool(2)的参数来得到更多的体验,当然,让
[java]view plaincopy
@Override
publicvoidrun() {
System.out.println(Thread.currentThread().getName() +"正在执行。。。");
}
变成一个无限循环,你可以得到更多的关于pool.shutdown()的用法。
五:单任务延迟连接池
http://www.cnblogs.com/dolphin0520/p/3932934.html
http://blog.csdn.net/coding_or_coded/article/details/6856014
http://www.cnblogs.com/micrari/p/5634447.html