携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第九天,点击查看活动详情
目前的需求是,使用定时任务加线程池执行数据库操作时,会同时插入相同的数据,希望线程池执行时,不同的id可以同时执行查询并插入数据库,相同的id等第一个id执行完成再执行下一个。
@Test
public void contextLoads() {
//进行异步任务列表
List<FutureTask<Integer>> futureTasks = new ArrayList<FutureTask<Integer>>();
//线程池 初始化十个线程 实现重用
ExecutorService executorService = Executors.newFixedThreadPool(10);
long start = System.currentTimeMillis();
//测试多个id同时进入线程池,并执行操作,模拟多个相同的数据与不同的数据
List<String> list = new ArrayList();
list.add("a");
list.add("b");
list.add("a");
list.add("c");
list.add("a");
list.add("b");
for (int j = 0; j < 10; j++) {
for (int i = 0; i < list.size(); i++) {
final int t = i;
//创建一个异步任务
FutureTask<Integer> futureTask = new FutureTask<Integer>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
b(list.get(t));
return 1;
}
});
futureTasks.add(futureTask);
executorService.submit(futureTask);
}
int count = 0;
for (FutureTask<Integer> futureTask : futureTasks) {
//futureTask.get() 得到我们想要的结果
//该方法有一个重载get(long timeout, TimeUnit unit) 第一个参数为最大等待时间,第二个为时间的单位
try {
//执行完成后,记录所有执行的结果
count += futureTask.get(600, TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("线程池" + j + "的任务全部完成:结果为:" + count);
}
//执行完成关闭线程池
executorService.shutdown();
long end = System.currentTimeMillis();
//记录线程池所耗费的时间
System.out.println("使用时间:" + (end - start) + "ms");
}
public void b(String a) {
//如果a参数是new出来的,则用a.intern()
synchronized (a) {
System.out.println(a + " " + Thread.currentThread().getName() + " 进入处理--");
try {
//休眠一段时间,模拟业务逻辑操作
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(a + " " + Thread.currentThread().getName() + " 处理结束---");
}
}
运行出来的结果如下:
可以看到,已经实现了之前的需求,不同的id可以同时执行查询并插入数据库,相同的id等第一个id执行完成再执行下一个