线程池类似数据库连接池,在线程池中,总有那么几个活跃的线程。当你需要使用线程时,可以从池子中随便拿一个空闲的线程使用,待完成工作,将线程归还给线程池。
Executors类扮演着线程工厂的角色,使用该类的静态方法可以获取特点功能的线程池。
该方法返回固定线程数量的线程池。LinkedBlockingQueue
public static class MyTask implements Runnable{
@Override
public void run() {
//获取当前时间的毫秒数+:Thread Id:+当前线程的Id作为标识
String threadName = System.currentTimeMillis()+
":Thread Id:"+Thread.currentThread().getId();
System.out.println(threadName+"start");
try {
//sleep()不会释放锁,wait会释放锁
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName+"end");
}
}
public static void main(String[] args) {
MyTask task = new MyTask();
ExecutorService executorService = Executors.newFixedThreadPool(5);
System.out.println("main:"+Thread.currentThread().getId()+"start");
for(int i=0;i<10;i++){
executorService.submit(task);
}
System.out.println("main:"+Thread.currentThread().getId()+"end");
}
main:1start
1604731505456:Thread Id:11start
1604731505456:Thread Id:12start
1604731505456:Thread Id:12end
1604731506473:Thread Id:12start
1604731505456:Thread Id:11end
1604731506473:Thread Id:12end
main:1end
该方法返回一个只有一个线程的线程池。LinkedBlockingQueue
该方法返回一个可根据实际情况调整线程数量的线程池。当开启10个线程时,通过id可知,线程池中加有10个线程,该方法会根据cpu的资源占用自动调整线程池的大小。SynchronousQueue
public static void main(String[] args) {
MyTask task = new MyTask();
ExecutorService executorService = Executors.newCachedThreadPool();
System.out.println("main:"+Thread.currentThread().getId()+"start");
for(int i=0;i<10;i++){
executorService.submit(task);
}
try {
Thread.sleep(5000);
System.out.println("main:"+Thread.currentThread().getId()+"end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
该方法返回一个ScheduledExecutorService对象,线程池大小为1。可以实现线程周期性执行和延迟执行。
该方法返回一个ScheduledExecutorService对象,可指定线程池的线程数量。
/**
command:任务
delay:延迟时间
TimeUnit:单位 给定单元粒度的时间段
**/
schedule(Runnable command,long delay, TimeUnit unit);
/**
command:任务
initialDelay:初始延迟时间
period:周期的时间
unit:单位
第一次:initialDelay+0*period
第二次:initialDelay+1*period
...
**/
scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit)
/**
command:任务
initialDelay:初始延迟时间
delay:延迟时间
第一次:initialDelay
第二次:第一次的结束时间+delay
**/
scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit)
注意:任务遇到异常,后续的所有子任务都会停止调度。
以上介绍的线程池都是基于ThreadPoolExecutor类的封装
ThreadPoolExecutor(int corePoolSize,//指定线程池中的线程数量
int maximumPoolSize,//指定线程池中的最大线程数
long keepAliveTime,
/**
当线程池中的线程数超过corePoolSize,
多余空闲线程的存活时间
**/
TimeUnit unit,//时间单位
BlockingQueue<Runnable> workQueue,//任务队列
ThreadFactory threadFactory,//线程工厂
RejectedExecutionHandler handler)//决绝策略
workQueue:提交但未执行的任务队列。
handler:拒绝策略,当任务数量超过了系统的负载,就会使用到拒绝策略。
ThreadFactory:线程工厂是一个接口。只定义了一个用来创建线程的方法。
public interface ThreadFactory {
Thread newThread(Runnable r);
}
ThreadPoolExecutor 是一个可以扩展的线程池。它提供了beforeExecutor()、afterExecutor()/terminated()三个接口用来对线程池进行控制。
public class MyThreadPool {
public static class MyTask implements Runnable{
private String name;
public MyTask(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println("正在执行"+":Thread Id"+Thread.currentThread().getId()
+",Task Name"+name);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
ExecutorService es = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>()){
@Override
protected void beforeExecute(Thread t, Runnable r) {
System.out.println("准备执行:"+((MyTask) r).name);
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
System.out.println("执行完成:"+((MyTask) r).name);
}
@Override
protected void terminated() {
System.out.println("线程池退出");
}
};
for(int i=0;i<5;i++){
MyTask myTask = new MyTask("Task"+i);
es.execute(myTask);
Thread.sleep(10);
}
es.shutdown();
}
}
越学习,自己越渺小…刚步入多线程的学习大军,希望大家一起学习一起进步。