java_线程池
程序员文章站
2022-05-04 17:58:24
...
线程池
(1)如果每个任务都需要创建线程对象,内存开销大
(2)方便管理线程对象
线程池的原理
就是一些线程的集合,线程的状态不是死亡状态,当线程池接收到外面的任务时,线程池会查看是否有空闲线程,若有,就会将任务分配给它,任务处于等待队列中
线程池类型:ExecutorService
Executors里提供了多个静态方法来获取线程池对象
Executors的四个常用方法
方法1
static ExecutorService newSingleThreadExecutor()
获取单个线程的线程池对象,内部维护了一个*队列,用来存储任务
/**
* 单个线程的线程池,维护了一个*队列
*/
public class ThreadPoolDemo01 {
public static void main(String[] args) {
/*获取线程池对象*/
ExecutorService pool =
Executors.newSingleThreadExecutor();
/*创建5个任务*/
Task r1 = new Task("A");
Task r2 = new Task("B");
Task r3 = new Task("C");
Task r4 = new Task("D");
Task r5 = new Task("E");
/*
* 此线程池:会按照添加任务的顺序执行任务
* */
pool.execute(r1);
pool.execute(r2);
pool.execute(r3);
pool.execute(r4);
pool.execute(r5);
System.out.println("main()结束");
}
}
/**
* 添加任务Task
*/
class Task implements Runnable{
private String name;
public Task(String name) {
this.name = name;
}
public void run() {
synchronized (Task.class) {
for(int i=1;i<=3;i++){
System.out.println(name+":"+i);
}
}
}
}
方法2
static ExecutorService newFixedThreadPool(int nThreads)
创建一个固定数量(nThreads)线程的线程池
public class ThreadPoolDemo02 {
public static void main(String[] args) {
ExecutorService pool =
Executors.newFixedThreadPool(2);
Task r1 = new Task("A");
Task r2 = new Task("B");
Task r3 = new Task("C");
Task r4 = new Task("D");
Task r5 = new Task("E");
/*
* 此线程池:会按照添加任务的顺序执行任务
* 但是,如果任务体较短,控制台的输出打印顺序可能会乱序
* 可以使用Thread.sleep()来减缓输出打印的速度
* */
pool.execute(r1);
pool.execute(r2);
pool.execute(r3);
pool.execute(r4);
pool.execute(r5);
System.out.println("main()结束");
}
}
添加Thread.sleep(100);后
两个线程对象并发执行任务,执行完后,接取新任务继续执行
方法3
static ExecutorService newCachedThreadPool()
创建一个可以根据需求来创建新线程的线程池对象,若有可重用的,会优先使用
当添加任务进入线程池时,有空线程,线程池管理器将此任务分配给一个空线程
public class ThreadPoolDemo03 {
public static void main(String[] args) {
ExecutorService pool =
Executors.newCachedThreadPool();
Runnable r1 = new Run(1);
Runnable r2 = new Run(2);
Runnable r3 = new Run(3);
Runnable r4 = new Run(4);
Runnable r5 = new Run(5);
pool.execute(r1);
pool.execute(r2);
pool.execute(r3);
pool.execute(r4);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
/*当添加任务进入线程池时,有空线程,线程池管理器将此任务分配给一个空线程*/
pool.execute(r5);
}
}
class Run implements Runnable{
private int version;
public Run(){}
public Run(int version){
this.version = version;
}
@Override
public void run() {
for(int i=1;i<=3;i++){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(
Thread.currentThread().getName()+
"任务"+version+":"+i);
}
}
}
可以看到上述线程池对象一共创建了4个线程对象,而非5个。
前4个任务是并发执行的,每个任务都需要一个线程对象来执行,最后一个任务延迟了5秒后线程池对象才接收到,此时线程池中存在空闲的线程对象,故不再产生新的线程对象,将任务随机分配给其中一个空闲线程对象。
方法4
static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
创建一个线程池,可以进行设置延迟或定时执行任务
public class ThreadPoolDemo04 {
public static void main(String[] args) {
/*延时是ScheduledExecutorService自己独有的方法,父接口ExecutorService没有延时的方法*/
ScheduledExecutorService pool =
Executors.newScheduledThreadPool(2);
Runnable r1 = new Run(1);
Runnable r2 = new Run(2);
Runnable r3 = new Run(3);
Runnable r4 = new Run(4);
Runnable r5 = new Run(5);
pool.execute(r1);
pool.execute(r2);
pool.execute(r3);
pool.execute(r4);
pool.schedule(r5, 15, TimeUnit.SECONDS);//延迟15s
pool.shutdown();//关闭线程池
}
}