Java多线程之线程池详解
线程池概念
存放多个线程对象的资源池
用于提高启动多个线程的性能(类比连接池)
当程序中涉及创建大量生存期很短的线程,推荐使用线程池。
内置线程池
- SingleThreadPool:创建一个单线程化的线程池,只有唯一一个线程来执行任务,保证所有任务按照指定顺序执行(可能是先进先出,后进先出,优先级别)
- FixedThreadPool:创建可以可以重用的固定数量的线程池。
- CachedThreadPool:创建一个根据需要可新增线程的线程池。
- ScheduledThreadPool:创建一个定长的线程池,支持定时及周期性任务调度。
线程池源码简单解析
线程池类的层次图:
Executor:顶层接口,接受线程任务并且执行
ExecutorService:添加了一些其他方法。ThreadPoolExecutor:添加了一些常规的线程池,Single,Fixed,Cached
或许有的同学觉得这几参数比较难理解所以我这给出一个简化版本
corePoolSize - 核心线程数
maximumPoolSize - 最大线程数。
keepAliveTime - 线程存活时间
unit -时间单位设置
keepAliveTime-任务缓存队列
Executor:工具类,创建不同的线程池。
ScheduleThreadPoolExecutor:调度的线程池
线程池的简单应用
SingleThreadPool
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolTest01 {
public static void main(String[] args) {
//创建SingleThreadPool线程池
ExecutorService pool = Executors.newSingleThreadExecutor();
//创建FixedThreadPool线程池,并且定义为3个线程的线程池
ExecutorService pool = Executors.newFixedThreadPool(3);
//创建CachedThreadPool线程池
ExecutorService pool = Executors.newCachedThreadPool();
//创建很多个任务
TaskTest t1 = new TaskTest("t1");//创建任务1
TaskTest t2 = new TaskTest("t2");//创建任务2
TaskTest t3 = new TaskTest("t3");//创建任务3
TaskTest t4 = new TaskTest("t4");//创建任务4
TaskTest t5 = new TaskTest("t5");//创建任务5
pool.execute(t1);//执行t1
pool.execute(t2);//执行t2
pool.execute(t3);//执行t3
pool.execute(t4);//执行t4
pool.execute(t5);//执行t5
pool.shutdown();//关闭
}
}
class TaskTest implements Runnable{
private String name; //任务名字
public TaskTest(String name) {
this.name = name;
}
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getName()+"正在执行"+name);
}
}
SingleThreadPool运行结果
可以看出,所有任务都是由线程1来完成的,满足只有唯一一个线程来执行任务,保证所有任务按照指定顺序执行。
FixedThreadPool运行结果:
满足所有线程都由创建的三个线程来完成
CachedThreadPool运行结果:
满足线程的增加
调度线程池
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ScheduledExecutorTest02 {
public static void main(String[] args) {
SET t1 = new SET("t1");
SET t2 = new SET("t2");
//创建有两个线程的调度线程池
ScheduledThreadPoolExecutor sche = new ScheduledThreadPoolExecutor(2);
sche.scheduleAtFixedRate(t1,1,1,TimeUnit.SECONDS);//设置t1调度参数
sche.scheduleAtFixedRate(t2,1,1,TimeUnit.SECONDS);//设置t2调度参数
}
}
class SET implements Runnable{
private String name; //任务名字
public SET(String name) {
this.name = name;
}
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getName()+"正在执行"+name);
}
}
运行结果
问题:调度线程池中的线程是否跟任务绑定,还是到调度时间,重新分配?
回答:通过上图画红线得出答案,是到调度时间重新分配。
还没有评论,来说两句吧...