1.多线程工具类
package com.atguigu.common.utils;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.util.Map;
import java.util.concurrent.*;
/**
* @ClassName ThreadPoolUtil
* @Description 多线程工具类
* @Author mischen
* @Date 2022/10/13 16:19
* @Version 1.0
**/
public class ThreadPoolUtil {
//每个任务都有自己单独的线程池
private static Map<String, ExecutorService> executorServiceMap = new ConcurrentHashMap<>();
//初始化一个线程池
private static ExecutorService init(String poolName,int poolSize){
return new ThreadPoolExecutor(
poolSize,poolSize,0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
new ThreadFactoryBuilder().setNameFormat("Pool-"+poolName).setDaemon(false).build(),
new ThreadPoolExecutor.CallerRunsPolicy());
}
//获取线程池
public static ExecutorService getOrInitExecutors(String poolName,int poolSize){
ExecutorService executorService = executorServiceMap.get(poolName);
if (null == executorService){
synchronized (ThreadPoolUtil.class){
executorService = executorServiceMap.get(poolName);
if (null == executorService){
executorService = init(poolName,poolSize);
executorServiceMap.put(poolName,executorService);
}
}
}
return executorService;
}
//回收线程资源
public static void releaseExecutors(String poolName){
ExecutorService executorService = executorServiceMap.remove(poolName);
if (executorService!=null){
executorService.shutdown();
}
}
}
2.Cat类
package com.atguigu.common.to;
import lombok.Data;
@Data
public class Cat {
private String catName;
public Cat setCatName(String name) {
this.catName = name;
return this;
}
}
3.ChildTask类
package com.atguigu.common.utils;
import com.atguigu.common.to.Cat;
import com.google.common.collect.Lists;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
public class ChildTask {
private final int POOL_SIZE = 3; // 线程池大小
private final int SPLIT_SIZE = 4; // 数据拆分大小
private String taskName;
// 接收jvm关闭信号,实现优雅停机
protected volatile boolean terminal = false;
public ChildTask(String taskName) {
this.taskName = taskName;
}
// 程序执行入口
public void doExecute() {
int i = 0;
while(true) {
System.out.println(taskName + ":Cycle-" + i + "-Begin");
// 获取数据
List<Cat> datas = queryData();
// 处理数据
taskExecute(datas);
System.out.println(taskName + ":Cycle-" + i + "-End");
if (terminal) {
// 只有应用关闭,才会走到这里,用于实现优雅的下线
break;
}
i++;
}
// 回收线程池资源
ThreadPoolUtil.releaseExecutors(taskName);
}
// 优雅停机
public void terminal() {
// 关机
terminal = true;
System.out.println(taskName + " shut down");
}
// 处理数据
private void doProcessData(List<Cat> datas, CountDownLatch latch) {
try {
for (Cat cat : datas) {
System.out.println(taskName + ":" + cat.toString() + ",ThreadName:" + Thread.currentThread().getName());
Thread.sleep(1000L);
}
} catch (Exception e) {
System.out.println(e.getStackTrace());
} finally {
if (latch != null) {
latch.countDown();
}
}
}
// 处理单个任务数据
private void taskExecute(List<Cat> sourceDatas) {
if (CollectionUtils.isEmpty(sourceDatas)) {
return;
}
// 将数据拆成4份
List<List<Cat>> splitDatas = Lists.partition(sourceDatas, SPLIT_SIZE);
final CountDownLatch latch = new CountDownLatch(splitDatas.size());
// 并发处理拆分的数据,共用一个线程池
for (final List<Cat> datas : splitDatas) {
ExecutorService executorService = ThreadPoolUtil.getOrInitExecutors(taskName, POOL_SIZE);
executorService.submit(new Runnable() {
@Override
public void run() {
doProcessData(datas, latch);
}
});
}
try {
latch.await();
} catch (Exception e) {
System.out.println(e.getStackTrace());
}
}
// 获取永动任务数据
private List<Cat> queryData() {
List<Cat> datas = new ArrayList<>();
for (int i = 0; i < 5; i ++) {
datas.add(new Cat().setCatName("测试---" + i));
}
return datas;
}
}
4.LoopTask类
package com.atguigu.common.utils;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
public class LoopTask {
private List<ChildTask> childTasks;
public void initLoopTask() {
childTasks = new ArrayList();
childTasks.add(new ChildTask("testTask1"));
childTasks.add(new ChildTask("testTask2"));
for (final ChildTask childTask : childTasks) {
new Thread(new Runnable() {
@Override
public void run() {
childTask.doExecute();
}
}).start();
}
}
public void shutdownLoopTask() {
if (!CollectionUtils.isEmpty(childTasks)) {
for (ChildTask childTask : childTasks) {
childTask.terminal();
}
}
}
public static void main(String args[]) throws Exception{
LoopTask loopTask = new LoopTask();
loopTask.initLoopTask();
Thread.sleep(5000L);
loopTask.shutdownLoopTask();
}
}
5.打印结果:
testTask1:Cycle-0-Begin
testTask2:Cycle-0-Begin
testTask1:Cat(catName=测试---0),ThreadName:Pool-testTask1
testTask2:Cat(catName=测试---0),ThreadName:Pool-testTask2
testTask1:Cat(catName=测试---4),ThreadName:Pool-testTask1
testTask2:Cat(catName=测试---4),ThreadName:Pool-testTask2
testTask1:Cat(catName=测试---1),ThreadName:Pool-testTask1
testTask2:Cat(catName=测试---1),ThreadName:Pool-testTask2
testTask1:Cat(catName=测试---2),ThreadName:Pool-testTask1
testTask2:Cat(catName=测试---2),ThreadName:Pool-testTask2
testTask1:Cat(catName=测试---3),ThreadName:Pool-testTask1
testTask2:Cat(catName=测试---3),ThreadName:Pool-testTask2
testTask1:Cycle-0-End
testTask1:Cycle-1-Begin
testTask2:Cycle-0-End
testTask2:Cycle-1-Begin
testTask1:Cat(catName=测试---4),ThreadName:Pool-testTask1
testTask2:Cat(catName=测试---4),ThreadName:Pool-testTask2
testTask1:Cat(catName=测试---0),ThreadName:Pool-testTask1
testTask2:Cat(catName=测试---0),ThreadName:Pool-testTask2
testTask1 shut down
testTask2 shut down
testTask1:Cat(catName=测试---1),ThreadName:Pool-testTask1
testTask2:Cat(catName=测试---1),ThreadName:Pool-testTask2
testTask2:Cat(catName=测试---2),ThreadName:Pool-testTask2
testTask1:Cat(catName=测试---2),ThreadName:Pool-testTask1
testTask1:Cat(catName=测试---3),ThreadName:Pool-testTask1
testTask2:Cat(catName=测试---3),ThreadName:Pool-testTask2
testTask2:Cycle-1-End
testTask1:Cycle-1-End