系统启动一个新线程的成本式比较高的,因为它涉及到与操作系统交互。这种情况下,使用线程池可以很好地提高性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更应该考虑使用线程池。
线程池再系统启动的时候,就创建大量空闲的线程,程序将一个Runnable对象或者Callable对象传给线程池,线程池就会启动一个线程来执行他们的run()或者call()方法,当run()或call()方法执行结束后,该线程并不会死亡,而是再次进入线程池中成为空闲状态,等待下一个Runnable对象的run()或call()方法。
使用线程池可以有效地控制系统中并发线程的数量,当系统中包含大量并发线程时,会导致系统性能剧烈下降,甚至导致JVM崩溃,而线程池的最大线程数参数可以控制系统中并发线程数不超过此数。
java5新增了一个Executors工厂类来产生线程池。该工厂类包含以下几个静态工厂方法来创建线程池:
1、newCachedThreadPool()
2、newFixedThreadPool(int nThreads)
3、newSingleThreadExecutor()
4、newScheduledThreadPool(int corePoolSize)
5、newSingleThreadScheduledExecutor()
6、ExecutorService newWorkStealingPool(int parallelism)
7、ExecutorService newWorkStealingPool()
ExecutorService代表尽快执行线程的线程池(只要线程池中有空闲线程,就立即执行线程任务),程序只要将一个Runnable对象或Callable对象提交给线程池,,该线程池就会尽快执行任务。ExecutorService里提供了3个方法:
1、Future<?>submit(Runnable task)
2、<T>Future<T>submit(Runnable task,T result)
3、<T>Future<T>submit(Callable<T>)
ScheduleExecutorService代表可在指定延迟后或周期性地执行线程任务的线程池,它提供了如下4个方法:
1、ScheduleFuture<V>schedule(Callable<V>callable,long delay,TimeUnit unit)
2、ScheduleFuture<V>schedule(Runnable command,long delay,TimeUnit unit)
3、ScheduleFuture<V>scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit)
4、ScheduleFuture<V>scheduleWithFixedDelay(Runnable command,long initialDelay,long period,TimeUnit unit)
用完一个线程池后,应该调用该线程池的shutdown()方法,该方法将启动线程池的关闭序列,调用shutdown()方法后的线程池不再接收新任务,但会将以前所有已提交任务执行完成。当线程池中的所有任务都执行完成后,池中的所有线程都会死亡;另外也可以调用线程池的shutdownNow()方法来关闭线程池,该方法试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表。
使用线程池来执行县城任务的步骤如下:
1、调用Executor对象的静态工厂方法创建一个ExecutorService对象,代表一个线程池
2、创建Runnable实现类或Callable实现类的实例,作为线程执行任务
3、调用ExecutorService对象的submit()方法来提交Runnable实例会Callable实例
4、当不想提交任何任务时,调用ExecutorService对象的shutdown()方法来关闭线程池
看如下代码:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolTest {
public static void main(String[] args) {
//创建一个具有固定线程数(6)的线程池
ExecutorService pool = Executors.newFixedThreadPool(6);
//shiyong Lambda表达式创建Runnable
Runnable target = ()->{
for(int i=0;i<100;i++) {
System.out.println(Thread.currentThread().getName()+" 的i值为:"+i);
}
};
//向线程池中提交两个线程
pool.submit(target);
pool.submit(target);
//关闭线程池
pool.shutdown();
}
}
运行结果:
(参考《疯狂Java讲义第3版》)