本文代码来自网络,我自己按理解重新贴一下。
来源
网址:http://blog.51cto.com/gggcgba/1437919
本文主要实现在多任务下,如何指定线程分发任务。比如100条任务,分发给四个线程。
想要实现的效果如下:
线程1执行任务第0——24
线程2执行任务第25——49
线程3执行任务第50——74
线程4执行任务75——99
具体实现方法如下。
包含三个类:任务分发类、任务类、线程执行类
定义任务类:
execute()方法是想要执行的具体业务。
package com.alpha.thread; public class Task { public static final int READY = 0; public static final int RUNNING = 1; public static final int FINISHED = 2; @SuppressWarnings("unused") private int status; // 声明一个任务的自有业务含义的变量,用于标识任务 private int taskId; private String storeCode; // 任务的初始化方法 public Task(int taskId,String storeCode) { this.status = READY; this.taskId = taskId; this.storeCode=storeCode; } /** * 执行任务 */ public void execute() { // 设置状态为运行中 setStatus(Task.RUNNING); System.out.println("当前线程 ID 是:" + Thread.currentThread().getName() + " | 任务 ID 是:" + this.taskId+" |门店号为:"+this.storeCode); // 附加一个延时 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } // 执行完成,改状态为完成 setStatus(FINISHED); } public void setStatus(int status) { this.status = status; } public int getTaskId() { return taskId; } }
线程执行类:重新实现Thread类,构造工作线程,为其指派任务列表,及命名线程 ID。
package com.alpha.thread; import java.util.List; public class WorkThread extends Thread{ // 本线程待执行的任务列表,你也可以指为任务索引的起始值 private List<Task> taskList = null; @SuppressWarnings("unused") private int threadId; /** * 构造工作线程,为其指派任务列表,及命名线程 ID * * @param taskList * 欲执行的任务列表 * @param threadId * 线程 ID */ @SuppressWarnings("unchecked") public WorkThread(List taskList, int threadId) { this.taskList = taskList; this.threadId = threadId; } /** * 执行被指派的所有任务 */ public void run() { for (Task task : taskList) { task.execute(); } } }
任务分发类:
package com.alpha.thread; import java.util.ArrayList; import java.util.List; public class TaskDistributor { /** * 测试方法 * @param args */ @SuppressWarnings("unchecked") public static void main(String[] args) { // 初始化要执行的任务列表 List taskList = new ArrayList(); for (int i = 0; i < 100; i++) { taskList.add(new Task(i,i+":store")); } // 设定要启动的工作线程数为 4 个 int threadCount = 4; List[] taskListPerThread = distributeTasks(taskList, threadCount); System.out.println("实际要启动的工作线程数:" + taskListPerThread.length); for (int i = 0; i < taskListPerThread.length; i++) { Thread workThread = new WorkThread(taskListPerThread[i], i); workThread.start(); } } @SuppressWarnings("unchecked") public static List[] distributeTasks(List taskList, int threadCount) { // 每个线程至少要执行的任务数,假如不为零则表示每个线程都会分配到任务 int minTaskCount = taskList.size() / threadCount; // 平均分配后还剩下的任务数,不为零则还有任务依个附加到前面的线程中 int remainTaskCount = taskList.size() % threadCount; // 实际要启动的线程数,如果工作线程比任务还多 // 自然只需要启动与任务相同个数的工作线程,一对一的执行 // 毕竟不打算实现了线程池,所以用不着预先初始化好休眠的线程 int actualThreadCount = minTaskCount > 0 ? threadCount:remainTaskCount; // 要启动的线程数组,以及每个线程要执行的任务列表 List[] taskListPerThread = new List[actualThreadCount]; int taskIndex = 0; // 平均分配后多余任务,每附加给一个线程后的剩余数,重新声明与 remainTaskCount // 相同的变量,不然会在执行中改变 remainTaskCount 原有值,产生麻烦 int remainIndces = remainTaskCount; for (int i = 0; i < taskListPerThread.length; i++) { taskListPerThread[i] = new ArrayList(); // 如果大于零,线程要分配到基本的任务 if (minTaskCount > 0) { for (int j = taskIndex; j < minTaskCount + taskIndex; j++) { taskListPerThread[i].add(taskList.get(j)); } taskIndex += minTaskCount; } // 假如还有剩下的,则补一个到这个线程中 if (remainIndces > 0) { taskListPerThread[i].add(taskList.get(taskIndex++)); remainIndces--; } } // 打印任务的分配情况 for (int i = 0; i < taskListPerThread.length; i++) { System.out.println("线程 "+i+ "的任务数:" + taskListPerThread[i].size()+ " 区间[" + ((Task) taskListPerThread[i].get(0)).getTaskId() + "," + ((Task) taskListPerThread[i].get(taskListPerThread[i].size() - 1)) .getTaskId() + "]"); } return taskListPerThread; } }
执行结果:
线程 0的任务数:25 区间[0,24]
线程 1的任务数:25 区间[25,49]
线程 2的任务数:25 区间[50,74]
线程 3的任务数:25 区间[75,99]
实际要启动的工作线程数:4
当前线程 ID 是:Thread-0 | 任务 ID 是:0 |门店号为:0:store
当前线程 ID 是:Thread-1 | 任务 ID 是:25 |门店号为:25:store
当前线程 ID 是:Thread-2 | 任务 ID 是:50 |门店号为:50:store
当前线程 ID 是:Thread-3 | 任务 ID 是:75 |门店号为:75:store
当前线程 ID 是:Thread-0 | 任务 ID 是:1 |门店号为:1:store
当前线程 ID 是:Thread-1 | 任务 ID 是:26 |门店号为:26:store
当前线程 ID 是:Thread-2 | 任务 ID 是:51 |门店号为:51:store
当前线程 ID 是:Thread-3 | 任务 ID 是:76 |门店号为:76:store
当前线程 ID 是:Thread-0 | 任务 ID 是:2 |门店号为:2:store
当前线程 ID 是:Thread-1 | 任务 ID 是:27 |门店号为:27:store
当前线程 ID 是:Thread-2 | 任务 ID 是:52 |门店号为:52:store
当前线程 ID 是:Thread-3 | 任务 ID 是:77 |门店号为:77:store
当前线程 ID 是:Thread-0 | 任务 ID 是:3 |门店号为:3:store
线程 1的任务数:25 区间[25,49]
线程 2的任务数:25 区间[50,74]
线程 3的任务数:25 区间[75,99]
实际要启动的工作线程数:4
当前线程 ID 是:Thread-0 | 任务 ID 是:0 |门店号为:0:store
当前线程 ID 是:Thread-1 | 任务 ID 是:25 |门店号为:25:store
当前线程 ID 是:Thread-2 | 任务 ID 是:50 |门店号为:50:store
当前线程 ID 是:Thread-3 | 任务 ID 是:75 |门店号为:75:store
当前线程 ID 是:Thread-0 | 任务 ID 是:1 |门店号为:1:store
当前线程 ID 是:Thread-1 | 任务 ID 是:26 |门店号为:26:store
当前线程 ID 是:Thread-2 | 任务 ID 是:51 |门店号为:51:store
当前线程 ID 是:Thread-3 | 任务 ID 是:76 |门店号为:76:store
当前线程 ID 是:Thread-0 | 任务 ID 是:2 |门店号为:2:store
当前线程 ID 是:Thread-1 | 任务 ID 是:27 |门店号为:27:store
当前线程 ID 是:Thread-2 | 任务 ID 是:52 |门店号为:52:store
当前线程 ID 是:Thread-3 | 任务 ID 是:77 |门店号为:77:store
当前线程 ID 是:Thread-0 | 任务 ID 是:3 |门店号为:3:store