多线程同步处理(线程安全)
一、如果每个线程进行操作的是同一份数据,相互会产生影响,就要使用线程安全
1. 假设某店某商品库存为3件,有3个销售,每个销售都看成一个线程。
public class SyncSale implements Runnable {
private String name;
private int count;
@Override
public void run() {
count--;
System.out.println(Thread.currentThread().getName()+"销售了1件"+name+"商品,还剩下"+count+"件");
}
public SyncSale(String name, int count) {
this.name = name;
this.count = count;
}
}
2. 测试
配置类中加入线程池
@Bean(name = "taskExecutor")
public TaskExecutor workExecutor() {
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setThreadNamePrefix("marThread-");
threadPoolTaskExecutor.setCorePoolSize(3);// 线程池维护线程的最少数量
threadPoolTaskExecutor.setMaxPoolSize(10);// 线程池维护线程的最大数量
threadPoolTaskExecutor.setQueueCapacity(10);// 缓存队列
threadPoolTaskExecutor.setKeepAliveSeconds(300);// 允许的空闲时间
threadPoolTaskExecutor.afterPropertiesSet();
return threadPoolTaskExecutor;
}
controller中调用
@RequestMapping(value = "/syncSale", method = RequestMethod.POST)
public void sale(HttpServletRequest request, HttpServletResponse response) throws IOException {
SyncSale sale = new SyncSale("A",3);
taskExecutor.execute(sale);
taskExecutor.execute(sale);
taskExecutor.execute(sale);
}
使用postman测试结果
2018-12-27 16:55:51.619 INFO com.mar.MarApplication Line:59 -
Started MarApplication in 5.93 seconds (JVM running for 7.02)
marThread-1销售了1件A商品,还剩下1件
marThread-3销售了1件A商品,还剩下0件
marThread-2销售了1件A商品,还剩下1件
如图,多线程对同一库存(同一对象)进行操作时就会出现安全问题,因此需要保证多线程并发时线程安全,数据唯一性、有序性。
3. 此处在代码块上加synchronized 保证同时只能有一个线程在修改库存。
public void run() {
synchronized (this){
count--;
System.out.println(Thread.currentThread().getName()+"销售了1件,
还剩下"+count+"件");
}
}
4. 测试
2018-12-27 17:15:29.319 INFO com.mar.MarApplication Line:59 -
Started MarApplication in 6.156 seconds (JVM running for 7.282)
marThread-1销售了1件A商品,还剩下2件
marThread-3销售了1件A商品,还剩下1件
marThread-2销售了1件A商品,还剩下0件
这就满足了我们实际需求。