线程池
1、为什么要创建线程池?
(1)创建线程的开销很大
(2)预先建立好线程,有一个固定的预先线程数目,等待任务派发,任务完成后再回到线程池
2、线程池的参数
(1)corePoolSize 初始线程数量
(2)maximumPoolSize 最大允许的线程数量
(3)keepAliveTime 线程等待时间。超出初始线程数目的线程,如果超出等待时间将被回收
3、Java Executor Framework
先演示一个的简单的例子
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
//设定一个初始线程数量与最大数量都为3的线程池
ExecutorService service=Executors.newFixedThreadPool(3);
//分配10个任务,这10个任务加入到一个先进先出的队列中,供线程完成
//传入任务id,用来查看任务的完成情况
for(int i=0;i<10;i++){
service.submit(new WriteTask(i));
}
//主线程结束
System.out.println("main thread finish");
}
}
其中WriteTask为
public class WriteTask implements Runnable {
private final int id;
public WriteTask(int id) {
this.id = id;
}
@Override
public void run() {
System.out.println(id+" start");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(id+" end");
}
}
运行结果
运行结果分析:
(1)刚开始时,有三个线程,用来完成编号为0 1 2的三个任务,这三个线程执行的顺序不定,因此会出现012的随机排列
(2)只有前三个任务完成时,接下来的三个任务才能开始(因为最多只有三个线程在执行)
(3)main函数结束的时候,这个程序并没有结束(main thread finish出现在最前面,接下来才是线程完成任务)
如果我想在10个任务全部完成的时候,退出这个线程池,该怎么操作?
依据:submit(Runnable r)会返回一个Future<?>,将其加入到一个list中,随后遍历这个list,使用Future<?>对象的get()方法,若线程执行完成,get()方***返回null(因为我用的Runnable,run()没有返回值),若未执行完成,则主线程一直处于等待状态。
具体代码
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Main {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//设定一个初始线程数量与最大数量都为3的线程池
ExecutorService service=Executors.newFixedThreadPool(3);
//记录任务完成情况的list
List<Future<?>> list=new LinkedList<>();
//分配10个任务,这10个任务加入到一个先进先出的队列中,供线程完成
//传入任务id,用来查看任务的完成情况
for(int i=0;i<10;i++){
Future<?> task=service.submit(new WriteTask(i));
list.add(task);
}
//主线程结束
System.out.println("main thread finish");
//判断10个任务是否完成
for(Future<?> future:list){
future.get();
}
System.out.print("所有的任务都已经完成");
//退出线程池
service.shutdown();
}
}
此时输出为
可以看得出,10个任务确实已经完成了,最后退出这个线程池,程序最终也退出了
不过其实shutdown()方***等待,等待线程池完成当前已经分配的全部任务后,主线程才会执行shutdown()方法