1、主要代码
@Component
public class BatchOperationThreadTaskUtil {
//工具类静态执行
private static PlatformTransactionManager transactionManager;
//此属性只是为了动态赋值给上面的属性
@Autowired
private PlatformTransactionManager remoteTransactionManager;
private static final Logger log = LoggerFactory.getLogger(BatchOperationThreadTaskUtil.class);
private static final int TIME = 30;
private static final int CORE_POOL_SIZE = 15;
private static final int MAXIMUM_POOL_SIZE = 15;
private static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, TIME, TimeUnit.MINUTES, new LinkedBlockingQueue(), new ThreadFactoryBuilder().setNameFormat("batchOperationThread-pool-%d").build());
//初始化时赋值给静态属性
@PostConstruct
public void init() {
this.transactionManager = this.remoteTransactionManager;
}
/**
* 多任务执行 开启多个线程
* @param executeBeans
* @param callable
*/
public static <T> void excute(Collection<T> executeBeans, CallableWithException<T> callable) throws Exception{
CountDownLatch mainLatch = new CountDownLatch(1);
CountDownLatch sampleLatch = new CountDownLatch(executeBeans.size());
AtomicBoolean rollBackFlag = new AtomicBoolean(false);
executeBeans.forEach(b->{
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
if(rollBackFlag.get()){
sampleLatch.countDown();
return;
}
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
TransactionStatus status = transactionManager.getTransaction(def);
try{
callable.call(b);
sampleLatch.countDown();
mainLatch.await();
if(rollBackFlag.get()){
transactionManager.rollback(status);
}else{
transactionManager.commit(status);
}
}catch (Exception e){
log.error("批量操作失败",e);
rollBackFlag.set(true);
sampleLatch.countDown();
transactionManager.rollback(status);
}
}
});
});
sampleLatch.await();
mainLatch.countDown();
if(rollBackFlag.get()){
throw new RuntimeException("批量操作失败");
}
}
}
2、动态执行代码块用到lambda
@FunctionalInterface
public interface CallableWithException<T>{
void call(T e) throws Exception;
}
3、具体使用
BatchOperationThreadTaskUtil.excute(yourlist,(item)->{
//具体业务代码块,尽量不要用外部对象引用,很容易造成数据库死锁
});