一、为什么要用线程池?
1)、系统启动一个新线程的成本是比较高的,因为它涉及与操作系统交互。在这种情形下,使用线程池可以很好地提高性能,尤其是当程序中需要创建大量生存期很短的线程时,更应该考虑使用线程池;使用线程池可以降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
2)、使用线程池可有有效地控制系统中并发线程的数量;当系统中包含大量并发线程时,会导致系统性能剧烈下降,甚至导致JVM崩溃,而线程池的最大线程参数可以控制系统中并发线程数;
线程池是为突然大量爆发的线程设计的,通过有限的几个固定线程为大量的操作服务,减少了创建和销毁线程所需的时间,从而提高效率。
如果一个线程的时间非常长,就没必要用线程池了(不是不能作长时间操作,而是不宜。),况且我们还不能控制线程池中线程的开始、挂起、和中止。
二、java8改进的线程池
1、线程池相关的接口和类
1)ExecutorService对象代表一个线程池;程序只要将一个Runnable对象或Callable对象(代表线程任务)提交给线程池,只要线程池中有空闲线程,就会立即执行线程任务;
public interface Executor {
void execute(Runnable command);
}
public interface ExecutorService extends Executor{
void shutdown();
List<Runnable> shutdownNow();
boolean isShutdown();
boolean isTerminated();
boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
/* Future代表Callable对象的call()方法的返回值 */
<T> Future<T> submit(Callable<T> task);
/* result显示指定线程执行结束后的返回值,所以Future对象在run()执行结束后返回result */
<T> Future<T> submit(Runnable task, T result);
/*因为Runnable中的run()没有返回值,所Future在run()执行结束后返回null,但可以调有Future.isDone()或isCancelled()来获取Runnable对象的执行状态 */
Future<?> submit(Runnable task);
// ...其他方法
}
public interface ScheduledExecutorService extends ExecutorService {
/* 指定command任务将在delay延迟后执行 */
public ScheduledFuture<?> schedule(Runnable command,
long delay, TimeUnit unit);
public <V> ScheduledFuture<V> schedule(Callable<V> callable,
long delay, TimeUnit unit);
/* 指定command任务将在delay延迟后执行,而且以设定频率重复执行 */
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit);
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
long initialDelay,
long delay,
TimeUnit unit);
}
2、四种常用线程池创建方式
1)Executors工具类
java1.5新增了一个Executors工厂类来生产线程池ExecutorService;该工厂类提供的四种常用方法如下:
- newFixedThreadPool(int nThreads):创建一个可复用的,具有固定线程数的线程池;
- newFixedThreadPool(int nThreads, ThreadFactory threadFactory)
- newSingleThreadExecutor():创建一个只有一个线程的线程池。
- newSingleThreadExecutor(ThreadFactory threadFactory)
- newCachedThreadPool():创建一个具有缓存功能的线程池。
- newCachedThreadPool(ThreadFactory threadFactory)
- newSingleThreadScheduledExecutor()
- newSingleThreadScheduledExecutor(ThreadFactory threadFactory)
- newScheduledThreadPool(int corePoolSize):创建具有指定线程数的线程池,它可以在指定延迟时间后执行。
- newWorkStealingPool(int parallelism)
2)使用线程池来执行线程任务的步骤
public class ExecutorServiceDemo {
public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
/**
* 使用线程池来执行线程任务的步骤如下:
* 1)调用Executors工厂类方法创建一个线程池对象ExecutorService;
* 2)创建Runnable类或Callable类的实例,作为线程执行任务;
* 3)调用ExecutorService.submit()来执行Runnable或Callable类的实例;
* 4)当不想提交任何任务时,调用ExecutorService.shutdown()方法关闭线程池;
*/
ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
Future future = pool.submit(new TaskTest(),"success");
System.out.println(future.get(10, TimeUnit.SECONDS));
pool.shutdown();
}
}
class TaskTest implements Runnable{
@Override
public void run() {
System.out.println("正在执行任务。。。。");
}
}