作用
线程池在系统启动的时候即创建大量的空闲线程,程序将Runnable对象或者Callable对象传给线程池。线程池就会启动一个线程来执行他们的run( )或call( )方法,执行结束后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待执行下一个Runnable对象的run( )或者call( )方法。
Java通过Executors提供四种线程池,分别为:
newCachedThreadPool(): 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool(int nThread): 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool(int n): 创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor(): 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
上述方法返回ExecutorService(接口)对象:
几个非常重要的方法:
execute()
submit()
shutdown()
shutdownNow()
execute() 方法实际上是Executor中声明的方法,在ThreadPoolExecutor进行了具体的实现,这个方法是ThreadPoolExecutor的核心方法,通过这个方法可以向线程池提交一个任务,交由线程池去执行。
Future<?> submit(Runnable task);
<T> Future<T> submit(Callable<T> task);
submit() 方法是在ExecutorService中声明的方法,在AbstractExecutorService就已经有了具体的实现,在ThreadPoolExecutor中并没有对其进行重写,这个方法也是用来向线程池提交任务的,但是它和execute()方法不同,它能够返回任务执行的结果,去看submit()方法的实现,会发现它实际上还是调用的execute()方法,只不过它利用了Future来获取任务执行结果(Future相关内容将在下一篇讲述)。
shutdown()和shutdownNow()是用来关闭线程池的。
创建步骤
使用线程池执行任务的步骤:
-
调用
Executors
类的静态方法创建一个ExecutorService
对象,该对象代表一个线程池。 -
创建
Runnable
实现类或者Callable
实现类的实例,作为线程执行任务。 -
调用
ExecutorService
对象的submit()
方法提交Runnable实例
或者Callable实例
。 -
当不想提交任务时,调用ExecutorService对象的
shutdown( )
方法来关闭线程池。
代码实验
import java.util.concurrent.*;
public class Main1
{
public static void main(String[] args)
throws Exception
{
// 创建足够的线程来支持4个CPU并行的线程池
// 创建一个具有固定线程数(6)的线程池
ExecutorService pool = Executors.newFixedThreadPool(6);
// 使用Lambda表达式创建Runnable对象
Runnable target = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100 ; i++ )
{
System.out.println(Thread.currentThread().getName()
+ "的i值为:" + i);
}
}
};
// 向线程池中提交两个线程
pool.submit(target);
Thread.sleep(1);
pool.submit(target);
// 关闭线程池
pool.shutdown();
}
}
...
pool-1-thread-1的i值为:95
pool-1-thread-1的i值为:96
pool-1-thread-1的i值为:97
pool-1-thread-1的i值为:98
pool-1-thread-1的i值为:99
pool-1-thread-2的i值为:0
pool-1-thread-2的i值为:1
pool-1-thread-2的i值为:2
pool-1-thread-2的i值为:3
pool-1-thread-2的i值为:4
...