线程的调用是随机的,但是有个需求是在线程池中开辟多个线程按顺序去执行一组任务,比如说一个任务组下面有多个子任务,需要按子任务的顺序依次提交
代码:
public class TestThread {
public static void main(String[] args) {
//创建线程池
ThreadPoolExecutor executorService = new ThreadPoolExecutor(10, 10,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(1024));
//创建任务组
List<TaskGroupVO> taskGroupVOS = getAllTaskGroup();
for (TaskGroupVO groupVO : taskGroupVOS) {
executorService.submit(()-> {
System.out.println("===============" + Thread.currentThread().getName() +":任务组" + groupVO.getTaskGroupName() + "开始执行===============");
for (TaskVO taskVO : groupVO.getTaskVOList()) {
System.out.println("执行:" + taskVO.getName());
LockSupport.park();
}
System.out.println("===============" + Thread.currentThread().getName() +":任务组" + groupVO.getTaskGroupName() + "结束执行===============");
});
}
}
//获取任务组列表
public static List<TaskGroupVO> getAllTaskGroup() {
List<TaskGroupVO> taskGroups = new ArrayList<>();
for (int i=1; i<=10; i++) {
List<TaskVO> taskVOS = new ArrayList<>();
TaskGroupVO taskGroupVO = new TaskGroupVO();
taskGroupVO.setId(i);
taskGroupVO.setTaskGroupName("任务组"+i);
taskGroupVO.setTaskPlanId(i);
for (int j=1; j<=4; j++) {
TaskVO taskVO = new TaskVO();
taskVO.setId(j);
taskVO.setName(taskGroupVO.getTaskGroupName() + ":任务" + j);
taskVOS.add(taskVO);
}
taskGroupVO.setTaskVOList(taskVOS);
taskGroups.add(taskGroupVO);
}
return taskGroups;
}
}
这里只能所有的任务组只能打印出任务1,因为LockSupport.park();将线程加了锁,需要释放锁之后才会继续执行,任务执行完成之后写一个回调方法将锁释放
//这里表示任务执行完成后的回调方法
public void callBack() {
Long threadId = map.get(datasetInfoDVO.getId());
if(threadId != null) {
Thread thread = findThread(threadId);
System.out.println("任务执行完成");
LockSupport.unpark(thread);
}
}
/**
* 通过线程组获得线程
*
* @param threadId
* @return
*/
public static Thread findThread(long threadId) {
ThreadGroup group = Thread.currentThread().getThreadGroup();
while(group != null) {
Thread[] threads = new Thread[(int)(group.activeCount() * 1.2)];
int count = group.enumerate(threads, true);
for(int i = 0; i < count; i++) {
if(threadId == threads[i].getId()) {
return threads[i];
}
}
group = group.getParent();
}
return null;
}
由此实现就可以看到打印出来的任务组中的子任务是顺序打印的了,这样写只在本地测试了,还没有正式上线运行,不确定正式环境是否会出现什么问题,如有不正确,欢迎指出~