在我的业务需求中,需要整合多个任务模块,然后在每个任务模块之间是依赖关系,前者执行完,才能执行后面的任务模块。
对于这样多任务,而且后端处理时间较长的处理逻辑,我的处理方案是,通过多线程的方式将任务加入到线程池中,然后主线程能够直接返回结果给前端,而每个功能模块的直接结果持久化到数据库中,前端的任务结果进度展示,通过轮询查看数据库中的记录情况来呈现。
下面是我制作的一个业务处理模型,在主线程入口处,创建一个Single线程池,能够保证这个线程池中的任务是FIFO,以队列进入顺序进行执行,这个而且这个线程池是没有被阻塞的,因此当所有任务进入该线程池队列中后,主线程就可以直接返回结果;然后各个任务模块被多线程分别调度执行。
下面给出简单模型及Demo代码:
在任务队列中,任务0是第一个队列,需要首先执行,然后子线程阻塞,等待任务0执行结束;随后任务1和任务2同时执行,子线程依然阻塞等待这两个任务执行结束;最后再执行任务3。
请求层
http://localhost:8080/deploy/autodeploy/threadPool
View层
/**
* [4] 多线程测试
*/
@RequestMapping("/autodeploy/threadPool")
public void threadPool(HttpServletRequest request, HttpServletResponse response) {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
ResultVo resultVo = new ResultVo();
resultVo.setCode(1);
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
singleThreadExecutor.execute(new Runnable() {
@Override
public void run() {
autoDeployService.threadPool1(10);
}
});
singleThreadExecutor.execute(new Runnable() {
@Override
public void run() {
autoDeployService.threadPool2(10);
}
});
singleThreadExecutor.execute(new Runnable() {
@Override
public void run() {
autoDeployService.threadPool3(10);
}
});
try {
response.getWriter().write(JsonUtil.getJson(resultVo));
response.getWriter().close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Service层
public class AutoDeployService extends BaseService {
private Logger logger = LoggerFactory.getLogger(ServerController.class.getName());
/**
* 测试 线程池1
*/
public void threadPool1(int count) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
final CountDownLatch latch = new CountDownLatch(count);
logger.info(" 线程池0 - 正在执行...");
for (int i = 0; i < count; i++) {
final int index = i;
executorService.execute(new Runnable() {
@Override
public void run() {
try {
logger.info("线程池0 - " + index);
Thread.sleep(2000);
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
// wait
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 测试 线程池2
*/
public void threadPool2(int count) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
final CountDownLatch latch = new CountDownLatch(count);
logger.info(" 线程池1/2 - 正在执行...");
for (int i = 0; i < count; i++) {
final int index = i;
executorService.execute(new Runnable() {
@Override
public void run() {
try {
logger.info("线程池1 - " + index);
logger.info("线程池2 - " + index);
Thread.sleep(1000);
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
// wait
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 测试 线程池3
*/
public void threadPool3(int count) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
CountDownLatch latch = new CountDownLatch(count);
logger.info(" 线程池3 - 正在执行...");
for (int i = 0; i < count; i++) {
final int index = i;
executorService.execute(new Runnable() {
@Override
public void run() {
try {
logger.info("线程池3 - " + index);
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
// wait
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
控制台输出结果
19:28:52.411 [pool-14-thread-1] INFO com.nkm.deploy.view.ServerController - 线程池0 - 正在执行...
19:28:52.413 [pool-15-thread-1] INFO com.nkm.deploy.view.ServerController - 线程池0 - 0
19:28:52.413 [pool-15-thread-2] INFO com.nkm.deploy.view.ServerController - 线程池0 - 1
19:28:52.414 [pool-15-thread-3] INFO com.nkm.deploy.view.ServerController - 线程池0 - 2
19:28:54.414 [pool-15-thread-2] INFO com.nkm.deploy.view.ServerController - 线程池0 - 4
19:28:54.414 [pool-15-thread-3] INFO com.nkm.deploy.view.ServerController - 线程池0 - 5
19:28:54.414 [pool-15-thread-1] INFO com.nkm.deploy.view.ServerController - 线程池0 - 3
19:28:56.414 [pool-15-thread-3] INFO com.nkm.deploy.view.ServerController - 线程池0 - 6
19:28:56.414 [pool-15-thread-1] INFO com.nkm.deploy.view.ServerController - 线程池0 - 7
19:28:56.414 [pool-15-thread-2] INFO com.nkm.deploy.view.ServerController - 线程池0 - 8
19:28:58.414 [pool-15-thread-1] INFO com.nkm.deploy.view.ServerController - 线程池0 - 9
19:29:00.414 [pool-14-thread-1] INFO com.nkm.deploy.view.ServerController - 线程池1/2 - 正在执行...
19:29:00.415 [pool-16-thread-1] INFO com.nkm.deploy.view.ServerController - 线程池1 - 0
19:29:00.415 [pool-16-thread-1] INFO com.nkm.deploy.view.ServerController - 线程池2 - 0
19:29:00.415 [pool-16-thread-2] INFO com.nkm.deploy.view.ServerController - 线程池1 - 1
19:29:00.415 [pool-16-thread-2] INFO com.nkm.deploy.view.ServerController - 线程池2 - 1
19:29:00.415 [pool-16-thread-3] INFO com.nkm.deploy.view.ServerController - 线程池1 - 2
19:29:00.415 [pool-16-thread-3] INFO com.nkm.deploy.view.ServerController - 线程池2 - 2
19:29:01.416 [pool-16-thread-3] INFO com.nkm.deploy.view.ServerController - 线程池1 - 3
19:29:01.416 [pool-16-thread-1] INFO com.nkm.deploy.view.ServerController - 线程池1 - 5
19:29:01.416 [pool-16-thread-2] INFO com.nkm.deploy.view.ServerController - 线程池1 - 4
19:29:01.416 [pool-16-thread-3] INFO com.nkm.deploy.view.ServerController - 线程池2 - 3
19:29:01.416 [pool-16-thread-1] INFO com.nkm.deploy.view.ServerController - 线程池2 - 5
19:29:01.416 [pool-16-thread-2] INFO com.nkm.deploy.view.ServerController - 线程池2 - 4
19:29:02.416 [pool-16-thread-2] INFO com.nkm.deploy.view.ServerController - 线程池1 - 8
19:29:02.416 [pool-16-thread-3] INFO com.nkm.deploy.view.ServerController - 线程池1 - 7
19:29:02.416 [pool-16-thread-1] INFO com.nkm.deploy.view.ServerController - 线程池1 - 6
19:29:02.416 [pool-16-thread-2] INFO com.nkm.deploy.view.ServerController - 线程池2 - 8
19:29:02.416 [pool-16-thread-3] INFO com.nkm.deploy.view.ServerController - 线程池2 - 7
19:29:02.416 [pool-16-thread-1] INFO com.nkm.deploy.view.ServerController - 线程池2 - 6
19:29:03.416 [pool-16-thread-1] INFO com.nkm.deploy.view.ServerController - 线程池1 - 9
19:29:03.416 [pool-16-thread-1] INFO com.nkm.deploy.view.ServerController - 线程池2 - 9
19:29:04.416 [pool-14-thread-1] INFO com.nkm.deploy.view.ServerController - 线程池3 - 正在执行...
19:29:04.417 [pool-17-thread-1] INFO com.nkm.deploy.view.ServerController - 线程池3 - 0
19:29:04.417 [pool-17-thread-2] INFO com.nkm.deploy.view.ServerController - 线程池3 - 1
19:29:04.417 [pool-17-thread-3] INFO com.nkm.deploy.view.ServerController - 线程池3 - 2
19:29:07.417 [pool-17-thread-2] INFO com.nkm.deploy.view.ServerController - 线程池3 - 3
19:29:07.417 [pool-17-thread-1] INFO com.nkm.deploy.view.ServerController - 线程池3 - 4
19:29:07.417 [pool-17-thread-3] INFO com.nkm.deploy.view.ServerController - 线程池3 - 5
19:29:10.417 [pool-17-thread-3] INFO com.nkm.deploy.view.ServerController - 线程池3 - 7
19:29:10.417 [pool-17-thread-2] INFO com.nkm.deploy.view.ServerController - 线程池3 - 8
19:29:10.417 [pool-17-thread-1] INFO com.nkm.deploy.view.ServerController - 线程池3 - 6
19:29:13.417 [pool-17-thread-3] INFO com.nkm.deploy.view.ServerController - 线程池3 - 9
前端请求调用的返回结果,这个结果在请求发送到后端,在后端业务逻辑还没有执行完,就马上返回到前端,因为执行的主线程是不存在阻塞的,只有子线程才有阻塞。
{
"code": 1
}