什么是线程池?
目的:减少对象创建和销毁的时间
Java线程池实现Java高并发、Java多线程、可管理的统一调度器
Executors是线程的工厂类(工具类):方便快速的创建线程池
创建线程池常见的3种方法
newSingleThreadExecutor 创建单线程的线程池
newFixedThreadPool 创建固定大小的线程池
newCachedThreadPool 创建可缓存线程池
线程池的优点
1.降低资源消耗(重复利用已创建线程)
2.提高响应速度
3.提高线程的可管理性
4.防止服务器过载,形成内存溢出
线程池工作机制
线程等待池 BlockingQueue
任务处理池PoolWorker,即正在工作的线程列表HashSet
核心池大小(corePoolSize) 线程池的稳定峰值,达到这个值之后的线程数大小不会释放的
最大处理线程池数(maxinumPoolSize) 线程池的线程数超过corePoolSize,小于maxPoolSize,会动态创建回收线程池内的资源
自定义线程池和ExecutorService
自定义线程池需要用到ThreadFactory
Executor : 执行线程池的工具
ExecutorService : 线程池的真正接口(继承了Executor)
AbstractExecutorService:实现ExecutorService接口
ThreadPoolExecutor:ExecutorService默认实现
ScheduleExecutorService:解决那些需要重复执行的问题
ScheduleThreadPoolExecutor:解决周期性调度问题的真正实现
Executors 工厂类(创建更多线程)
RejectedExecutionHandler
处理被丢弃的线程和异常的接口
ThreadPoolExecutor
线程池最核心的类
理解构造函数的参数
corePoolSize
maxinumPoolSize
keepAliveTime
TimeUnit
BlockingQueue
ThreadFactory
RejectedExecutionHandler
线程池注意问题
线程池是单例的,不能放在services方法种
线程数不能设置过大,会造成线程负载
注意死锁问题
/**
* ClassName:SingleThreadExecutorDemo
* Function: TODO 单例线程池
* Reason: TODO 只有一个线程池在工作(串行执行所有线程)
* 如果这个线程因为异常结束,会有新的线程替代它
* 保证所有任务的执行任务按提交任务顺序执行
* @author dzxla
* @version
* @since Ver 1.1
*/
public class SingleThreadExecutorDemo {
public static void main(String[] args) {
//代码实现使用了LinkedBlockingQueue
ExecutorService executor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int num = i;
Runnable t = new Runnable() {
@Override
public void run() {
System.out.println("into --> " + num);
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end --> " + num);
}
};
executor.execute(t);
}
executor.shutdown();
System.out.println("Thread Main End");
}
}
console
Thread Main End
into --> 0
end --> 0
into --> 1
end --> 1
into --> 2
end --> 2
into --> 3
end --> 3
into --> 4
end --> 4
into --> 5
end --> 5
into --> 6
end --> 6
into --> 7
end --> 7
into --> 8
end --> 8
into --> 9
end --> 9
public class FixedThreadPoolDemo {
public static void main(String[] args) {
//代码实现使用了LinkedBlockingQueue
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
final int num = i;
Runnable t = new Runnable() {
@Override
public void run() {
System.out.println("into --> " + num);
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end --> " + num);
}
};
executor.execute(t);
}
executor.shutdown();
System.out.println("Thread Main End");
}
}
console
into --> 1
into --> 4
Thread Main End
into --> 3
into --> 0
into --> 2
end --> 2
into --> 5
end --> 0
into --> 6
end --> 3
into --> 7
end --> 1
into --> 8
end --> 4
into --> 9
end --> 5
end --> 6
end --> 8
end --> 7
end --> 9
/**
* ClassName:CachedThreadPoolDemo
* Function: TODO 可缓存的线程池
* Reason: TODO 可重用之前的线程
* @author dzxla
* @version
* @since Ver 1.1
* @Date 2016年11月10日 下午3:22:40
*/
public class CachedThreadPoolDemo {
public static void main(String[] args) {
//实现了SynchronousQueue队列
ExecutorService executor = Executors.newCachedThreadPool();
for (int i = 0; i < 20; i++) {
final int num = i;
Runnable t = new Runnable() {
@Override
public void run() {
System.out.println("into --> " + num);
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end --> " + num);
}
};
executor.execute(t);
}
executor.shutdown();
System.out.println("Thread Main End");
}
}
console
into --> 0
into --> 2
into --> 1
into --> 3
into --> 4
into --> 5
into --> 6
into --> 7
into --> 8
into --> 9
into --> 10
into --> 11
into --> 12
into --> 13
Thread Main End
into --> 15
into --> 17
into --> 16
into --> 14
into --> 19
into --> 18
end --> 3
end --> 4
end --> 5
end --> 0
end --> 1
end --> 2
end --> 6
end --> 10
end --> 9
end --> 7
end --> 8
end --> 11
end --> 12
end --> 13
end --> 19
end --> 14
end --> 16
end --> 17
end --> 15
end --> 18
public class CustomThreadFactory implements ThreadFactory {
//原子操作进行计数
private static final AtomicInteger poolNum = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNum = new AtomicInteger(1);
private final String namePrefix;
CustomThreadFactory() {
SecurityManager sm = System.getSecurityManager();
group = (sm != null) ? sm.getThreadGroup() : Thread.currentThread().getThreadGroup();
namePrefix = "pool-" + poolNum.getAndIncrement() + "-thread-";
}
@Override
public Thread newThread(Runnable r) {
//自定义线程名称
Thread t = new Thread(group,r,namePrefix + threadNum.getAndIncrement(),0);
if(t.isDaemon()){
t.setDaemon(false);
}
if(t.getPriority() != Thread.NORM_PRIORITY){
t.setPriority(Thread.NORM_PRIORITY);
}
return t;
}
}
运行
public static void main(String[] args) {
Thread r = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("自定义线程池");
}
});
CustomThreadFactory factory = new CustomThreadFactory();
Thread t = factory.newThread(r);
System.out.println(t.getName());
t.start();
}
console
pool-1-thread-1
自定义线程池