Spring 线程@Async
@SpringBootApplication
@Slf4j
@EnableAsync //这个一定要开启
public class StartSipsApplication {
public static void main(String[] args) {
log.info("============= sips-fs 启动 ============");
SpringApplication.run(StartSipsApplication.class, args);
}
}}
@Slf4j
@Service
public class InboundEventListens implements CommandLineRunner {
@PostConstruct
public void init(){
System.out.println("init"+Thread.currentThread().getId());
}
@Override
@Async
public void run(String... args) throws Exception {
System.out.println("run"+Thread.currentThread().getId());
while (true){
System.out.println(new Date());
Thread.sleep(5000);
}
}
}
implements CommandLineRunner springboot初始化后会执行该方法 晚于@PostConstruct 执行
当去掉 @EnableAsync 时 线程ID是一样的。
加上注解后,线程ID是不一样的。
线程和事务
@Async + Transactional spring是生效的。
Stream.parallel()中使用事务
问题: 当我们使用stream().parallel()并行操作时,由于spring事务的单线程特性,无法有效在主线程执行预期的事务操作。
解决:
一、如同大多数多线程事务的处理方式,我们将事务细分化,对单个线程进行事务操作即可。
@Service
public class TestServiceA {
@Autowired
private TestServiceB serviceB;
/**
* 无效的事务
*/
@Transactional(rollbackFor = Exception.class)
public void testparallelStreamTransactin0(List<String> list) {
list.stream().parallel().forEach(e -> {
// do insert 1
// do insert 2
});
}
/**
* 有效的事务
*/
@Transactional(rollbackFor = Exception.class)
public void testparallelStreamTransactin1(List<String> list) {
list.stream().parallel().forEach(data -> {
serviceB.insert(data);
});
}
}
@Service
public class TestServiceB {
@Transactional(rollbackFor = Exception.class) //或者加个 @Async 也是有效事务
public void insert(String data){
// do insert 1
// do insert 2
}
}
难度升级,我想让多线程同步实现事务,一起成功或失败。这个时候就必须复杂了,不建议使用多变的且难以控制的steam parallel并发,建议使用线程池操作。大致思路如下:
1、定义线程共有事务管理器或者其集合,统一储存和管理事务,保证其多线程可见性;
2、在每个线程中使用事务管理器实现事务状态的标识,并记录,但要注意线程数量对性能的消耗
3、遍历,任务事务状态,最终统一执行事务的提交和回滚。