线程池

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()方法