线程池:
提供了一个线程队列,队列中保存着所有等待状态的线程。避免了创建与销毁额外开销,提高了响应的速度。
线程池的体系结构:
java.util.concurrent.Executor : 负责线程的使用与调度的根接口
|--ExecutorService 子接口: 线程池的主要接口
|--ThreadPoolExecutor 线程池的实现类
|--ScheduledExecutorService 子接口:负责线程的调度
|--ScheduledThreadPoolExecutor :继承 ThreadPoolExecutor, 实现 ScheduledExecutorService
Executor
Executor是一个接口,它将任务的提交与任务的执行分离开来,定义了一个接收Runnable对象的方法executor。Executor是Executor框架中最基础的一个接口,类似于集合中的Collection接口。
ExecutorService
ExecutorService继承了Executor,是一个比Executor使用更广泛的子类接口。定义了终止任务、提交任务、跟踪任务返回结果等方法。
一个ExecutorService是可以关闭的,关闭之后它将不能再接收任何任务,对于不在使用的ExecutorService,应该将其关闭以释放资源。
ExecutorService的方法
package java.util.concurrent;
import java.util.List;
import java.util.Collection;
public interface ExecutorService extends Executor {
/**
* 平滑地关闭线程池,已经提交到线程池中的任务会继续执行完。
*/
void shutdown();
/**
* 立即关闭线程池,返回还没有开始执行的任务列表。
* 会尝试中断正在执行的任务(每个线程调用 interruput方法),但这个行为不一定会成功。
*/
List<Runnable> shutdownNow();
/**
* 判断线程池是否已经关闭
*/
boolean isShutdown();
/**
* 判断线程池的任务是否已经执行完毕。
* 注意此方法调用之前需要先调用shutdown()方法或者shutdownNow()方法,否则总是会返回false
*/
boolean isTerminated();
/**
* 判断线程池的任务是否都执行完。
* 如果没有任务没有执行完毕则阻塞,直至任务完成或者达到了指定的timeout时间就会返回
*/
boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
/**
* 提交带有一个返回值的任务到线程池中去执行(回调),返回的 Future 表示任务的待定结果。
* 当任务成功完成后,通过 Future 实例的 get() 方法可以获取该任务的结果。
* Future 的 get() 方法是会阻塞的。
*/
<T> Future<T> submit(Callable<T> task);
/**
*提交一个Runnable的任务,当任务完成后,可以通过Future.get()获取的是提交时传递的参数T result
*
*/
<T> Future<T> submit(Runnable task, T result);
/**
* 提交一个Runnable的人无语,它的Future.get()得不到任何内容,它返回值总是Null。
* 为什么有这个方法?为什么不直接设计成void submit(Runnable task)这种方式?
* 这是因为Future除了get这种获取任务信息外,还可以控制任务,
具体体现在 Future的这个方法上:boolean cancel(boolean mayInterruptIfRunning)
这个方法能够去取消提交的Rannable任务。
*/
Future<?> submit(Runnable task);
/**
* 执行一组给定的Callable任务,返回对应的Future列表。列表中每一个Future都将持有该任务的结果和状态。
* 当所有任务执行完毕后,方法返回,此时并且每一个Future的isDone()方法都是true。
* 完成的任务可能是正常结束,也可以是异常结束
* 如果当任务执行过程中,tasks集合被修改了,那么方法的返回结果将是不确定的,
即不能确定执行的是修改前的任务,还是修改后的任务
*/
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException;
/**
* 执行一组给定的Callable任务,返回对应的Future列表。列表中每一个Future都将持有该任务的结果和状态。
* 当所有任务执行完毕后或者超时后,方法将返回,此时并且每一个Future的isDone()方法都是true。
* 一旦方法返回,未执行完成的任务被取消,而完成的任务可能正常结束或者异常结束,
* 完成的任务可以是正常结束,也可以是异常结束
* 如果当任务执行过程中,tasks集合被修改了,那么方法的返回结果将是不确定的
*/
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException;
/**
* 执行一组给定的Callable任务,当成功执行完(没抛异常)一个任务后此方法便返回,返回的是该任务的结果
* 一旦此正常返回或者异常结束,未执行的任务都会被取消。
* 如果当任务执行过程中,tasks集合被修改了,那么方法的返回结果将是不确定的
*/
<T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException;
/**
* 执行一组给定的Callable任务,当在timeout(超时)之前成功执行完(没抛异常)一个任务后此方法便返回,返回的是该任务的结果
* 一旦此正常返回或者异常结束,未执行的任务都会被取消。
* 如果当任务执行过程中,tasks集合被修改了,那么方法的返回结果将是不确定的
*/
<T> T invokeAny(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
线程池工具类 Executors :
ExecutorService newFixedThreadPool()
: 创建固定大小的线程池
ExecutorService newCachedThreadPool()
: 缓存线程池,线程池的数量不固定,可以根据需求自动的更改数量。
ExecutorService newSingleThreadExecutor()
: 创建单个线程池。线程池中只有一个线程
ScheduledExecutorService newScheduledThreadPool()
: 创建固定大小的线程,可以延迟或定时的执行任务。
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;
public class ThreadPoolDemo {
public static void main(String[] args) throws Exception {
fixedThreadPoolExecRunnableTask();
// fixedThreadPoolExecCallableTask();
// scheduledThreadPoolExecCallableTask();
}
// 创建固定大小的线程池, 执行 实现 Callable 接口 的线程任务, 可以延迟或定时的执行任务。
public static void scheduledThreadPoolExecCallableTask() throws Exception {
//1. 创建线程池 固定数量5个, 可以延迟或定时的执行任务。
ScheduledExecutorService pool = Executors.newScheduledThreadPool(5);
//2. 为线程池中的线程分配任务
for (int i = 0; i < 5; i++) {
// schedule(Callable<T> task)方法
Future<Integer> result = pool.schedule(new Callable<Integer>(){
@Override
public Integer call() throws Exception {
int num = new Random().nextInt(100);//生成随机数
System.out.println(Thread.currentThread().getName() + " : " + num);
return num;
}
}, 1, TimeUnit.SECONDS);
System.out.println(result.get());
}
//3. 关闭线程池
pool.shutdown();
}
// 创建固定大小的线程池, 执行 实现 Callable 接口 的线程任务
public static void fixedThreadPoolExecCallableTask() throws Exception {
//1. 创建线程池 固定数量5个
ExecutorService pool = Executors.newFixedThreadPool(5);
// 保存 线程任务 返回 的 Future 对象
List<Future<Integer>> list = new ArrayList<>();
//2. 为线程池中的线程分配任务
for (int i = 0; i < 10; i++) {
// submit(Callable<T> task)方法
Future<Integer> future = pool.submit(new Callable<Integer>() { // Callable
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 0; i <= 100; i++) {
sum += i;
}
return sum;
}
});
list.add(future);
}
//3. 关闭线程池
pool.shutdown();
// 遍历 线程任务 返回 的 Future 对象
for (Future<Integer> future : list) {
System.out.println(future.get());
}
}
// 创建固定大小的线程池, 执行 实现 Runnable 接口 的线程任务
public static void fixedThreadPoolExecRunnableTask() {
//1. 创建线程池 固定数量5个
ExecutorService pool = Executors.newFixedThreadPool(5);
//2. 为线程池中的线程分配任务
for (int i = 0; i < 10; i++) {
pool.submit(new Runnable() { // Runnable
private int i = 0;
@Override
public void run() {
while(i <= 100){
System.out.println(Thread.currentThread().getName() + " : " + i++);
}
}
});
}
//3. 关闭线程池
pool.shutdown();
}
}