使用線程池的方式有許多種,可以使用JDK自帶的Executors類中創建線程池的方式。通過源碼可以看出都是使用new ThreadPoolExecutor來創建線程池的。
import com.google.common.collect.Lists;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import lombok.Builder;
import lombok.Data;
/**
* @author :wangyongkang
* @date :Created in 2019/12/17 5:28 下午
* @description: 自定義一個線程池
* @modified By:
* @version:
*/
public class CustomThreadPool {
/**
* corePoolSize:核心線程數,即時是空閒的也不會被回收,除非設置allowCoreThreadTimeOut=true纔會被回收。
* maximumPoolSize:最大線程數。
* keepAliveTime:超過核心線程的其它線程的存活時間。
* unit:超過核心線程的其它線程的存活時間單位。
* workQueue:當任務塞滿了所有的線程,任務會被存放在queue中。
* threadFactory:創建新線程使用的Factory。
* handler:當任務數量達到了(maxPoolSize+queue)的數量,其它的任務不會處理,會調用rejectedExecution()方法。
*/
private ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,
4,
10,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(2),
new MyThreadPoolFactory(),
new MyRejectedExecutionHandler());
public static void main(String[] args) {
new CustomThreadPool().submitMethod();
}
/**
* 整個執行流程
* 1、一開始線程池中沒有線程。
* 2、有任務進來,便會啓動core pool size。
* 3、當超過core pool size,便會將任務放到queue中。
* 4、當超過core pool size + queue,啓動max pool size來處理任務。
* 5、當超過core pool size + queue,啓動(max pool size)-(core pool size)來處理任務。
* 6、當超過max pool size + queue,調用rejectedExecution()方法。
* 7、所有任務處理完成,(max pool size)-(core pool size)會被回收。
* <p>
* 注意: 如果BlockingDeque的Capacity沒有設置大小。則只會使用core pool size去處理任務。
*/
public void submitMethod() {
System.out.println("threads pool size:" + threadPoolExecutor.getPoolSize());
//任務List<MyTask>
List<MyTask> myTaskList = Lists.newArrayList();
//任務結果List<Future<MyTask>>,返回線程的一些信息
List<Future<MyTask>> futureList = Lists.newArrayList();
int i = 0;
while (i < 10) {
myTaskList.add(MyTask.builder().name("task" + (i++)).build());
}
myTaskList.forEach(o -> {
futureList.add(threadPoolExecutor.submit(o));
});
System.out.println("threads pool size:" + threadPoolExecutor.getPoolSize());
System.out.println("futureList-->:" + futureList);
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("threads pool size:" + threadPoolExecutor.getPoolSize());
}
}
/**
* 自定義ThreadPoolFactory
* 抄一下Executors是怎麼寫的
*/
class MyThreadPoolFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
MyThreadPoolFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-";
}
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon()) {
t.setDaemon(false);
}
if (t.getPriority() != Thread.NORM_PRIORITY) {
t.setPriority(Thread.NORM_PRIORITY);
}
return t;
}
}
/**
* 自定義RejectedExecutionHandler
* 抄一下Executors是怎麼寫的
*/
class MyRejectedExecutionHandler implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
try {
throw new RejectedExecutionException(
"Task " + r.toString() + " rejected from " + e.toString());
} catch (RejectedExecutionException re) {
System.out.println(re.getMessage());
re.printStackTrace();
}
}
}
/**
* 自定義Callable
*/
@Data
@Builder
class MyTask implements Callable<MyTask> {
private String name;
@Override
public MyTask call() {
System.out.println("ThreadName:" + Thread.currentThread().getName() + ",taskName:" + name);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return this;
}
}