为什么要使用线程池?
在Java中,创建一个线程只需要通过 new Thread(),就可以创建一个线程。那么创建一个线程需要经历以下几个步骤:
- 1、创建(T1:向操作系统申请内存)
- 2、运行(T2:执行run方法中业务)
- 3、销毁(T3:销毁当前线程并释放资源)
所以,在每一次new出一个线程需要消耗的时间为T1+T2+T3,可以发现,只有运行的业务不同,其他时间都不属于业务处理时间,因此可以复用 。
使用线程池的好处
-
可以降低资源的消耗
-
提高响应速度
-
提高线程的可管理性
自己实现一个线程池(简化版ThreadPoolExecutor)
在此,使用到了以下几个类:smallThreadPool(线程池实现)、testThreadPool(线程池测试类)、smallQueue(自定义实现队列,在并发编程 - 跳表、写时复制容器、阻塞队列中实现) -
smallThreadPool类代码:
package threadPool;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import queue.smallQueue;
//简化版,移除最大线程数、线程过期时间、过期单位,仅保留四个参数
public class smallThreadPool implements ExecutorService {
//定义一个存放任务的队列,此时使用我们之前写的queue,来处理
private final BlockingQueue<Runnable> blockingQueue;
//核心线程数
private final Thread[] coreThreads;
//已用线程数量
private final AtomicInteger enableThreadCount = new AtomicInteger(-1);
//未初始化线程数量
private final AtomicInteger notInitThreadCount;
//创建线程的工厂
private ThreadFactory threadFactory;
//任务满时淘汰策略
private RejectedExecutionHandler rejectedExecutionHandler;
public smallThreadPool() {
this(10);//如果没有传参,初始化任务数量为100个,线程池容量为10个
}
//通过构造传参初始化队列大小、线程池大小,此处忽略数字校验
public smallThreadPool(int coreThreadPoolSize,
ThreadFactory threadFactory,BlockingQueue<Runnable> blockingQueue,RejectedExecutionHandler rejectedExecutionHandler) {
this.blockingQueue = blockingQueue;
this.coreThreads = new Thread[coreThreadPoolSize];
this.threadFactory = threadFactory;
this.rejectedExecutionHandler = rejectedExecutionHandler;
this.notInitThreadCount = new AtomicInteger(coreThreadPoolSize);
//先初始化核心线程
for(int i=0;i<coreThreadPoolSize;i++){
coreThreads[i] = threadFactory.newThread(new MyTaskThread());
coreThreads[i].start();
}
}
public smallThreadPool(int coreThreadPoolSize) {
this(coreThreadPoolSize,Executors.defaultThreadFactory(),new smallQueue<>(coreThreadPoolSize),new RejectedExecutionHandler(){
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
throw new RuntimeException("任务["+r.toString() +"]超被抛弃了,因为当前没有空闲线程且队列已满了!");
}
});
}
//提交任务
@Override
public void execute(Runnable command) {
if(blockingQueue.offer(command)){
//添加成功
}else{
//添加失败,执行淘汰策略,由于是自定义实现,所以ThreadPoolExecutor不存在
rejectedExecutionHandler.rejectedExecution(command, null);
}
}
//关闭线程池
@Override
public void shutdown() {
for(int i=0;i<coreThreads.length;i++){
coreThreads[i].interrupt();
coreThreads[i] = null;
}
blockingQueue.clear();
}
@Override
public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
// TODO Auto-generated method stub
return null;
}
//继承Thread,重写run方法,让线程运行时,可以由我们自己来管理
private class MyTaskThread implements Runnable{
@Override
public void run() {
Runnable r = null;
while(!Thread.currentThread().isInterrupted()){
try {
r = blockingQueue.take();
if(r != null)
r.run();
System.out.println(Thread.currentThread().getName() + " - " + r.toString() + " 完成!");
r = null; //help GC
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
}
- testThreadPool类实现代码:
package threadPool;
import java.util.concurrent.TimeUnit;
public class testThreadPool {
private static class MyTask implements Runnable{
private String name;
public MyTask(String name) {
this.name = name;
}
public String getName(){
return name;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " - 处理:"+name);
TimeUnit.MILLISECONDS.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public String toString()