这篇文章是"
调度员,工人及任务的OO分析过程"的续篇.
上次的情况是由调度员主动分配任务,但有些情况下需要工人自动取得任务而不是由调度员分配,这时需要对线程进行通知,使用的主要方法就是对象的wait(),notify(),notifyAll()三个函数,它们都必须从同步方法(synchronized method)中调用.
这种情况下事务的大致流程是:工人从任务库中取得一项任务进行作业,完成后再取下一项,如果任务库中没有任务则进入等待状态,如果任务库有新任务则通知工人来取.
这次新引入了一个任务库类TaskLibrary,它取代了上次的调度员类,代码如下:
package com.sitinspring.autotask.domain;
import java.util.LinkedList;
import java.util.List;
/** *//**
* 任务库类
*
* @author sitinspring(junglesong@gmail.com)
*
*/
public class TaskLibrary {
private List<Task> tasks;
public TaskLibrary() {
tasks = new LinkedList<Task>();
}
// 添加单个任务
public synchronized void addTask(Task task) {
tasks.add(task);
notifyAll();
}
// 添加多个任务
public synchronized void addTasks(List<Task> moreTasks) {
tasks.addAll(moreTasks);
notifyAll();
}
public int getTaskSize() {
return tasks.size();
}
// 工人领受任务
public synchronized Task fetchTask(Worker worker) {
while (tasks.size() == 0) {
try {
System.out.println("任务告罄");
System.out.println("工人:" + worker.getName() + "进入闲置状态");
wait();
} catch (InterruptedException ex1) {
ex1.printStackTrace();
}
}
Task task = tasks.get(0);
System.out.println("工人:" + worker.getName() + "取得任务:" + task.getName());
tasks.remove(task);
return task;
}
}
其中,fetchTask通过调用wait方法,实现了没有任务时则对自己(this)加锁(lock),以让进入的线程等待,否则让工人取走最开头的任务.
而addTask和addTasks通过调用notifyAll方法,通知等待的线程可以继续进行原来陷入等待状态的流程.
在这种情况下,工人类只需关心当前任务即可,它无须保存一个任务列表,具体代码如下:
package com.sitinspring.autotask.domain;
import com.sitinspring.autotask.util.IdUtil;
public class Worker implements Runnable {
private String id;
private String name;
private Task currTask;
private TaskLibrary taskLibrary;
// 工作速度
private int speed;
public Worker(String name, int speed, TaskLibrary taskLibrary) {
id = IdUtil.generateId();
this.currTask = null;
this.name = name;
this.speed = speed;
this.taskLibrary = taskLibrary;
doWork();
}
// 开始干活
public void doWork() {
Thread thread = new Thread(this);
thread.start();
}
// 真正干活
public void run() {
while (true) {
if (currTask == null || currTask.isCompleted()) {
currTask = taskLibrary.fetchTask(this);
currTask.setWorker(this);
}
try {
Thread.sleep(1000);
System.out.println("正在处理的任务" + currTask + " 完成度"
+ currTask.getCompletedRatio() + "个.");
currTask.addCompleted(speed);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
}
它的Run方法实现了不断取活干活的过程,因为具体进入等待是TaskLibrary做的,所以这个类代码很简单,这里就不赘述了.
执行过程如下:
package com.sitinspring.autotask;
import java.util.LinkedList;
import java.util.List;
import com.sitinspring.autotask.domain.Task;
import com.sitinspring.autotask.domain.TaskLibrary;
import com.sitinspring.autotask.domain.Worker;
public class Test{
public static void main(String[] args){
TaskLibrary taskLibrary=new TaskLibrary();
taskLibrary.addTask(new Task("培训",8));
List<Task> moreTasks=new LinkedList<Task>();
moreTasks.add(new Task("锻造",4));
moreTasks.add(new Task("打磨",5));
moreTasks.add(new Task("车阶梯",6));
moreTasks.add(new Task("热处理",7));
moreTasks.add(new Task("去皮",8));
moreTasks.add(new Task("镗孔",60));
moreTasks.add(new Task("钻孔",10));
moreTasks.add(new Task("拉槽",11));
taskLibrary.addTasks(moreTasks);
Worker worker01=new Worker("王进喜",1,taskLibrary);
Worker worker02=new Worker("时传详",2,taskLibrary);
Worker worker03=new Worker("张秉贵",3,taskLibrary);
Worker worker04=new Worker("徐虎",3,taskLibrary);
taskLibrary.addTask(new Task("铸造",8));
sleep(1);
taskLibrary.addTask(new Task("校验",9));
sleep(2);
taskLibrary.addTask(new Task("内务",10));
sleep(3);
}
private static void sleep(int sleepSecond){
try{
Thread.sleep(sleepSecond*1000);
}
catch(Exception ex){
ex.printStackTrace();
}
}
}
执行效果如下:
工人:王进喜取得任务:培训
工人:时传详取得任务:锻造
工人:张秉贵取得任务:打磨
工人:徐虎取得任务:车阶梯
正在处理的任务任务名:培训 工人名:王进喜 完成度:0% 完成度 完成度:0%个.
正在处理的任务任务名:锻造 工人名:时传详 完成度:0% 完成度 完成度:0%个.
正在处理的任务任务名:打磨 工人名:张秉贵 完成度:0% 完成度 完成度:0%个.
正在处理的任务任务名:车阶梯 工人名:徐虎 完成度:0% 完成度 完成度:0%个.
正在处理的任务任务名:培训 工人名:王进喜 完成度:12% 完成度 完成度:12%个.
正在处理的任务任务名:锻造 工人名:时传详 完成度:50% 完成度 完成度:50%个.
任务任务名:锻造 工人名:时传详 完成度:100%处理完毕!
工人:时传详取得任务:热处理
正在处理的任务任务名:打磨 工人名:张秉贵 完成度:60% 完成度 完成度:60%个.
任务任务名:打磨 工人名:张秉贵 完成度:100%处理完毕!
正在处理的任务任务名:车阶梯 工人名:徐虎 完成度:50% 完成度 完成度:50%个.
任务任务名:车阶梯 工人名:徐虎 完成度:100%处理完毕!
工人:徐虎取得任务:去皮
工人:张秉贵取得任务:镗孔
正在处理的任务任务名:培训 工人名:王进喜 完成度:25% 完成度 完成度:25%个.
正在处理的任务任务名:热处理 工人名:时传详 完成度:0% 完成度 完成度:0%个.
正在处理的任务任务名:去皮 工人名:徐虎 完成度:0% 完成度 完成度:0%个.
正在处理的任务任务名:镗孔 工人名:张秉贵 完成度:0% 完成度 完成度:0%个.
正在处理的任务任务名:培训 工人名:王进喜 完成度:37% 完成度 完成度:37%个.
正在处理的任务任务名:热处理 工人名:时传详 完成度:28% 完成度 完成度:28%个.
正在处理的任务任务名:去皮 工人名:徐虎 完成度:37% 完成度 完成度:37%个.
正在处理的任务任务名:镗孔 工人名:张秉贵 完成度:5% 完成度 完成度:5%个.
正在处理的任务任务名:培训 工人名:王进喜 完成度:50% 完成度 完成度:50%个.
正在处理的任务任务名:热处理 工人名:时传详 完成度:57% 完成度 完成度:57%个.
正在处理的任务任务名:去皮 工人名:徐虎 完成度:75% 完成度 完成度:75%个.
任务任务名:去皮 工人名:徐虎 完成度:100%处理完毕!
工人:徐虎取得任务:钻孔
正在处理的任务任务名:镗孔 工人名:张秉贵 完成度:10% 完成度 完成度:10%个.
正在处理的任务任务名:培训 工人名:王进喜 完成度:62% 完成度 完成度:62%个.
正在处理的任务任务名:热处理 工人名:时传详 完成度:85% 完成度 完成度:85%个.
任务任务名:热处理 工人名:时传详 完成度:100%处理完毕!
工人:时传详取得任务:拉槽
正在处理的任务任务名:钻孔 工人名:徐虎 完成度:0% 完成度 完成度:0%个.
正在处理的任务任务名:镗孔 工人名:张秉贵 完成度:15% 完成度 完成度:15%个.
正在处理的任务任务名:培训 工人名:王进喜 完成度:75% 完成度 完成度:75%个.
正在处理的任务任务名:拉槽 工人名:时传详 完成度:0% 完成度 完成度:0%个.
正在处理的任务任务名:钻孔 工人名:徐虎 完成度:30% 完成度 完成度:30%个.
正在处理的任务任务名:镗孔 工人名:张秉贵 完成度:20% 完成度 完成度:20%个.
正在处理的任务任务名:培训 工人名:王进喜 完成度:87% 完成度 完成度:87%个.
任务任务名:培训 工人名:王进喜 完成度:100%处理完毕!
工人:王进喜取得任务:铸造
正在处理的任务任务名:拉槽 工人名:时传详 完成度:18% 完成度 完成度:18%个.
正在处理的任务任务名:钻孔 工人名:徐虎 完成度:60% 完成度 完成度:60%个.
正在处理的任务任务名:镗孔 工人名:张秉贵 完成度:25% 完成度 完成度:25%个.
正在处理的任务任务名:铸造 工人名:王进喜 完成度:0% 完成度 完成度:0%个.
正在处理的任务任务名:拉槽 工人名:时传详 完成度:36% 完成度 完成度:36%个.
正在处理的任务任务名:钻孔 工人名:徐虎 完成度:90% 完成度 完成度:90%个.
任务任务名:钻孔 工人名:徐虎 完成度:100%处理完毕!
工人:徐虎取得任务:校验
正在处理的任务任务名:镗孔 工人名:张秉贵 完成度:30% 完成度 完成度:30%个.
正在处理的任务任务名:铸造 工人名:王进喜 完成度:12% 完成度 完成度:12%个.
正在处理的任务任务名:拉槽 工人名:时传详 完成度:54% 完成度 完成度:54%个.
正在处理的任务任务名:校验 工人名:徐虎 完成度:0% 完成度 完成度:0%个.
正在处理的任务任务名:镗孔 工人名:张秉贵 完成度:35% 完成度 完成度:35%个.
正在处理的任务任务名:铸造 工人名:王进喜 完成度:25% 完成度 完成度:25%个.
正在处理的任务任务名:拉槽 工人名:时传详 完成度:72% 完成度 完成度:72%个.
正在处理的任务任务名:校验 工人名:徐虎 完成度:33% 完成度 完成度:33%个.
正在处理的任务任务名:镗孔 工人名:张秉贵 完成度:40% 完成度 完成度:40%个.
正在处理的任务任务名:铸造 工人名:王进喜 完成度:37% 完成度 完成度:37%个.
正在处理的任务任务名:拉槽 工人名:时传详 完成度:90% 完成度 完成度:90%个.
任务任务名:拉槽 工人名:时传详 完成度:100%处理完毕!
工人:时传详取得任务:内务
正在处理的任务任务名:校验 工人名:徐虎 完成度:66% 完成度 完成度:66%个.
任务任务名:校验 工人名:徐虎 完成度:100%处理完毕!
任务告罄
工人:徐虎进入闲置状态
正在处理的任务任务名:镗孔 工人名:张秉贵 完成度:45% 完成度 完成度:45%个.
正在处理的任务任务名:铸造 工人名:王进喜 完成度:50% 完成度 完成度:50%个.
正在处理的任务任务名:内务 工人名:时传详 完成度:0% 完成度 完成度:0%个.
正在处理的任务任务名:镗孔 工人名:张秉贵 完成度:50% 完成度 完成度:50%个.
正在处理的任务任务名:铸造 工人名:王进喜 完成度:62% 完成度 完成度:62%个.
正在处理的任务任务名:内务 工人名:时传详 完成度:20% 完成度 完成度:20%个.
正在处理的任务任务名:镗孔 工人名:张秉贵 完成度:55% 完成度 完成度:55%个.
正在处理的任务任务名:铸造 工人名:王进喜 完成度:75% 完成度 完成度:75%个.
正在处理的任务任务名:内务 工人名:时传详 完成度:40% 完成度 完成度:40%个.
正在处理的任务任务名:镗孔 工人名:张秉贵 完成度:60% 完成度 完成度:60%个.
正在处理的任务任务名:铸造 工人名:王进喜 完成度:87% 完成度 完成度:87%个.
任务任务名:铸造 工人名:王进喜 完成度:100%处理完毕!
任务告罄
工人:王进喜进入闲置状态
正在处理的任务任务名:内务 工人名:时传详 完成度:60% 完成度 完成度:60%个.
正在处理的任务任务名:镗孔 工人名:张秉贵 完成度:65% 完成度 完成度:65%个.
正在处理的任务任务名:内务 工人名:时传详 完成度:80% 完成度 完成度:80%个.
任务任务名:内务 工人名:时传详 完成度:100%处理完毕!
任务告罄
工人:时传详进入闲置状态
正在处理的任务任务名:镗孔 工人名:张秉贵 完成度:70% 完成度 完成度:70%个.
正在处理的任务任务名:镗孔 工人名:张秉贵 完成度:75% 完成度 完成度:75%个.
正在处理的任务任务名:镗孔 工人名:张秉贵 完成度:80% 完成度 完成度:80%个.
正在处理的任务任务名:镗孔 工人名:张秉贵 完成度:85% 完成度 完成度:85%个.
正在处理的任务任务名:镗孔 工人名:张秉贵 完成度:90% 完成度 完成度:90%个.
正在处理的任务任务名:镗孔 工人名:张秉贵 完成度:95% 完成度 完成度:95%个.
任务任务名:镗孔 工人名:张秉贵 完成度:100%处理完毕!
任务告罄
工人:张秉贵进入闲置状态
代码下载:
http://www.blogjava.net/Files/sitinspring/AutoTask20071020100536.rar