package com.dingxy.database.util;
import com.google.common.hash.Hashing;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author:
* @since: 2024/12/17 下午3:45
* @description:自定义有序线程池
* @version: 1.0 , Copyright (c) 2023 by ZTE Co.
*/
public class OrderedThreadPoolExecutor {
private final InnerTaskWorker[] taskWorkers;
private final ThreadFactory threadFactory;
public OrderedThreadPoolExecutor(int concurrency,ThreadFactory threadFactory){
this.taskWorkers = new InnerTaskWorker[concurrency];
this.threadFactory = threadFactory;
this.init(concurrency);
}
private void init(int concurrency){
this.initFillRunTasks(concurrency);
this.addShutdownHook();
}
/**
* 初始化填充并行任务
* @param taskCount 任务数,即并发度
*/
private void initFillRunTasks(int taskCount) {
for (int i = 0; i < taskCount; i++) {
this.taskWorkers[i] = new InnerTaskWorker(this.threadFactory);
}
}
/**
* 设置jvm退出的钩子,响应中断、释放资源
* 1. 不再接受新任务
* 2. 停止内部线程池
*/
private void addShutdownHook() {
Runtime.getRuntime().addShutdownHook(new Thread(() ->
Arrays.asList(this.taskWorkers).forEach(InnerTaskWorker::stopWorker)));
}
/**
* 根据提供的hashKey,执行有序的任务
* @param hashKey 分区标识
* @param task 任务
*/
public void executeOrdered(int hashKey, Runnable task) {
int i = hashKey % taskWorkers.length;
this.taskWorkers[i].addWorker(task);
}
private static final class InnerTaskWorker{
private final SynchronousQueue<Runnable> sq;
private final AtomicInteger threadState;
private final ThreadFactory threadFactory;
private volatile Thread command;
private InnerTaskWorker(ThreadFactory threadFactory){
this.sq = new SynchronousQueue<>();
this.threadState = new AtomicInteger(1);
this.threadFactory = threadFactory ;
this.init();
}
private void init(){
this.startWorker();
}
private Boolean isRunning(){
return this.threadState.get() == InnerThreadState.RUNNING;
}
private Boolean isTerminated(){
return this.threadState.get() == InnerThreadState.TERMINATED;
}
private void startWorker(){
this.command = threadFactory.newThread(()->{
while (this.isRunning()){
try {
sq.take().run();
} catch (InterruptedException e) {
if (this.isTerminated()){
throw new RuntimeException(e);
}
}catch (RuntimeException t){
this.handleWorkerException();
throw t;
}
}
});
this.command.start();
}
/**
* 处理任务异常时,继续有工作线程执行任务
*/
private void handleWorkerException() {
this.threadState.set(InnerThreadState.EXCEPTED);
// 通过cas方式来启动新线程
// 这个判断不是脱裤子放屁,因为threadState.set()与startWorker()并不是原子操作
if (this.threadState.compareAndSet(InnerThreadState.EXCEPTED, InnerThreadState.RUNNING)) {
this.startWorker();
}
}
private void addWorker(Runnable r){
try {
sq.put(r);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
private void stopWorker(){
this.threadState.set(InnerThreadState.TERMINATED);
this.command.interrupt();
try {
this.command.join();
} catch (InterruptedException e) {
System.out.println("abcdf");
}
}
}
public static void main(String[] args) {
OrderedThreadPoolExecutor orderedExecutor = new OrderedThreadPoolExecutor(64,new CustomThreadFactory("order-"));
Runnable task = () -> {
if (new Random().nextBoolean()) {
try {
System.out.println("hhahah");
Thread.sleep(20L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
// 模拟偶尔业务代码抛出异常情况
if (new Random().nextBoolean()) {
throw new RuntimeException("Test exception");
}
}
};
StringBuilder log = new StringBuilder();
for (int i = 0; i < 1000; i++) {
try {
String orderId = "o_" + (100_000_000 + i);
int hash = Math.abs(Hashing.murmur3_32().hashBytes(orderId.getBytes()).asInt());
orderedExecutor.executeOrdered(hash, task);
} catch (Exception ignore) {
// 忽略模拟的业务代码异常
}
}
InnerTaskWorker[] tws = orderedExecutor.taskWorkers;
for (int i = 0; i < tws.length; i++) {
log.append(tws[i].command.getName())
.append(" ==> ")
.append(tws[i].command.getState())
.append("\n");
}
System.out.println(log);
}
/* Started by AICoder, pid:6a35441173024a02956093915a9e1bca */
public static final class CustomThreadFactory implements ThreadFactory {
private final String namePrefix;
private final AtomicInteger threadId = new AtomicInteger(0);
public CustomThreadFactory(String namePrefix) {
this.namePrefix = namePrefix;
}
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, namePrefix + "-thread-" + threadId.getAndIncrement());
return t;
}
}
/* Ended by AICoder, pid:6a35441173024a02956093915a9e1bca */
/**
* 内部线程状态码
*/
private static final class InnerThreadState {
/**
* 正常运行
*/
private static final int RUNNING = 1;
/**
* 异常停止
*/
private static final int EXCEPTED = 2;
/**
* 正常结束
*/
private static final int TERMINATED = 3;
}
}
有序线程池(可根据订单号hash到同一个线程处理,适用于消息消费)
于 2024-12-20 15:56:52 首次发布
3040

被折叠的 条评论
为什么被折叠?



