這篇文章是"
調(diào)度員,工人及任務(wù)的OO分析過(guò)程"的續(xù)篇.
上次的情況是由調(diào)度員主動(dòng)分配任務(wù),但有些情況下需要工人自動(dòng)取得任務(wù)而不是由調(diào)度員分配,這時(shí)需要對(duì)線程進(jìn)行通知,使用的主要方法就是對(duì)象的wait(),notify(),notifyAll()三個(gè)函數(shù),它們都必須從同步方法(synchronized method)中調(diào)用.
這種情況下事務(wù)的大致流程是:工人從任務(wù)庫(kù)中取得一項(xiàng)任務(wù)進(jìn)行作業(yè),完成后再取下一項(xiàng),如果任務(wù)庫(kù)中沒(méi)有任務(wù)則進(jìn)入等待狀態(tài),如果任務(wù)庫(kù)有新任務(wù)則通知工人來(lái)取.
這次新引入了一個(gè)任務(wù)庫(kù)類TaskLibrary,它取代了上次的調(diào)度員類,代碼如下:
package com.sitinspring.autotask.domain;

import java.util.LinkedList;
import java.util.List;


/** *//**
* 任務(wù)庫(kù)類
*
* @author sitinspring(junglesong@gmail.com)
*
*/

public class TaskLibrary
{
private List<Task> tasks;


public TaskLibrary()
{
tasks = new LinkedList<Task>();
}

// 添加單個(gè)任務(wù)

public synchronized void addTask(Task task)
{
tasks.add(task);
notifyAll();
}

// 添加多個(gè)任務(wù)

public synchronized void addTasks(List<Task> moreTasks)
{
tasks.addAll(moreTasks);
notifyAll();
}


public int getTaskSize()
{
return tasks.size();
}

// 工人領(lǐng)受任務(wù)

public synchronized Task fetchTask(Worker worker)
{

while (tasks.size() == 0)
{

try
{
System.out.println("任務(wù)告罄");
System.out.println("工人:" + worker.getName() + "進(jìn)入閑置狀態(tài)");
wait();

} catch (InterruptedException ex1)
{
ex1.printStackTrace();
}
}

Task task = tasks.get(0);
System.out.println("工人:" + worker.getName() + "取得任務(wù):" + task.getName());
tasks.remove(task);
return task;
}
}
其中,fetchTask通過(guò)調(diào)用wait方法,實(shí)現(xiàn)了沒(méi)有任務(wù)時(shí)則對(duì)自己(this)加鎖(lock),以讓進(jìn)入的線程等待,否則讓工人取走最開(kāi)頭的任務(wù).
而addTask和addTasks通過(guò)調(diào)用notifyAll方法,通知等待的線程可以繼續(xù)進(jìn)行原來(lái)陷入等待狀態(tài)的流程.
在這種情況下,工人類只需關(guān)心當(dāng)前任務(wù)即可,它無(wú)須保存一個(gè)任務(wù)列表,具體代碼如下:
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();
}

// 開(kāi)始干活

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("正在處理的任務(wù)" + currTask + " 完成度"
+ currTask.getCompletedRatio() + "個(gè).");
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方法實(shí)現(xiàn)了不斷取活干活的過(guò)程,因?yàn)榫唧w進(jìn)入等待是TaskLibrary做的,所以這個(gè)類代碼很簡(jiǎn)單,這里就不贅述了.
執(zhí)行過(guò)程如下:
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("培訓(xùn)",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("王進(jìn)喜",1,taskLibrary);
Worker worker02=new Worker("時(shí)傳詳",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("校驗(yàn)",9));
sleep(2);
taskLibrary.addTask(new Task("內(nèi)務(wù)",10));
sleep(3);
}

private static void sleep(int sleepSecond)
{

try
{
Thread.sleep(sleepSecond*1000);
}

catch(Exception ex)
{
ex.printStackTrace();
}
}
}
執(zhí)行效果如下:
工人:王進(jìn)喜取得任務(wù):培訓(xùn)
工人:時(shí)傳詳取得任務(wù):鍛造
工人:張秉貴取得任務(wù):打磨
工人:徐虎取得任務(wù):車階梯
正在處理的任務(wù)任務(wù)名:培訓(xùn) 工人名:王進(jìn)喜 完成度:0% 完成度 完成度:0%個(gè).
正在處理的任務(wù)任務(wù)名:鍛造 工人名:時(shí)傳詳 完成度:0% 完成度 完成度:0%個(gè).
正在處理的任務(wù)任務(wù)名:打磨 工人名:張秉貴 完成度:0% 完成度 完成度:0%個(gè).
正在處理的任務(wù)任務(wù)名:車階梯 工人名:徐虎 完成度:0% 完成度 完成度:0%個(gè).
正在處理的任務(wù)任務(wù)名:培訓(xùn) 工人名:王進(jìn)喜 完成度:12% 完成度 完成度:12%個(gè).
正在處理的任務(wù)任務(wù)名:鍛造 工人名:時(shí)傳詳 完成度:50% 完成度 完成度:50%個(gè).
任務(wù)任務(wù)名:鍛造 工人名:時(shí)傳詳 完成度:100%處理完畢!
工人:時(shí)傳詳取得任務(wù):熱處理
正在處理的任務(wù)任務(wù)名:打磨 工人名:張秉貴 完成度:60% 完成度 完成度:60%個(gè).
任務(wù)任務(wù)名:打磨 工人名:張秉貴 完成度:100%處理完畢!
正在處理的任務(wù)任務(wù)名:車階梯 工人名:徐虎 完成度:50% 完成度 完成度:50%個(gè).
任務(wù)任務(wù)名:車階梯 工人名:徐虎 完成度:100%處理完畢!
工人:徐虎取得任務(wù):去皮
工人:張秉貴取得任務(wù):鏜孔
正在處理的任務(wù)任務(wù)名:培訓(xùn) 工人名:王進(jìn)喜 完成度:25% 完成度 完成度:25%個(gè).
正在處理的任務(wù)任務(wù)名:熱處理 工人名:時(shí)傳詳 完成度:0% 完成度 完成度:0%個(gè).
正在處理的任務(wù)任務(wù)名:去皮 工人名:徐虎 完成度:0% 完成度 完成度:0%個(gè).
正在處理的任務(wù)任務(wù)名:鏜孔 工人名:張秉貴 完成度:0% 完成度 完成度:0%個(gè).
正在處理的任務(wù)任務(wù)名:培訓(xùn) 工人名:王進(jìn)喜 完成度:37% 完成度 完成度:37%個(gè).
正在處理的任務(wù)任務(wù)名:熱處理 工人名:時(shí)傳詳 完成度:28% 完成度 完成度:28%個(gè).
正在處理的任務(wù)任務(wù)名:去皮 工人名:徐虎 完成度:37% 完成度 完成度:37%個(gè).
正在處理的任務(wù)任務(wù)名:鏜孔 工人名:張秉貴 完成度:5% 完成度 完成度:5%個(gè).
正在處理的任務(wù)任務(wù)名:培訓(xùn) 工人名:王進(jìn)喜 完成度:50% 完成度 完成度:50%個(gè).
正在處理的任務(wù)任務(wù)名:熱處理 工人名:時(shí)傳詳 完成度:57% 完成度 完成度:57%個(gè).
正在處理的任務(wù)任務(wù)名:去皮 工人名:徐虎 完成度:75% 完成度 完成度:75%個(gè).
任務(wù)任務(wù)名:去皮 工人名:徐虎 完成度:100%處理完畢!
工人:徐虎取得任務(wù):鉆孔
正在處理的任務(wù)任務(wù)名:鏜孔 工人名:張秉貴 完成度:10% 完成度 完成度:10%個(gè).
正在處理的任務(wù)任務(wù)名:培訓(xùn) 工人名:王進(jìn)喜 完成度:62% 完成度 完成度:62%個(gè).
正在處理的任務(wù)任務(wù)名:熱處理 工人名:時(shí)傳詳 完成度:85% 完成度 完成度:85%個(gè).
任務(wù)任務(wù)名:熱處理 工人名:時(shí)傳詳 完成度:100%處理完畢!
工人:時(shí)傳詳取得任務(wù):拉槽
正在處理的任務(wù)任務(wù)名:鉆孔 工人名:徐虎 完成度:0% 完成度 完成度:0%個(gè).
正在處理的任務(wù)任務(wù)名:鏜孔 工人名:張秉貴 完成度:15% 完成度 完成度:15%個(gè).
正在處理的任務(wù)任務(wù)名:培訓(xùn) 工人名:王進(jìn)喜 完成度:75% 完成度 完成度:75%個(gè).
正在處理的任務(wù)任務(wù)名:拉槽 工人名:時(shí)傳詳 完成度:0% 完成度 完成度:0%個(gè).
正在處理的任務(wù)任務(wù)名:鉆孔 工人名:徐虎 完成度:30% 完成度 完成度:30%個(gè).
正在處理的任務(wù)任務(wù)名:鏜孔 工人名:張秉貴 完成度:20% 完成度 完成度:20%個(gè).
正在處理的任務(wù)任務(wù)名:培訓(xùn) 工人名:王進(jìn)喜 完成度:87% 完成度 完成度:87%個(gè).
任務(wù)任務(wù)名:培訓(xùn) 工人名:王進(jìn)喜 完成度:100%處理完畢!
工人:王進(jìn)喜取得任務(wù):鑄造
正在處理的任務(wù)任務(wù)名:拉槽 工人名:時(shí)傳詳 完成度:18% 完成度 完成度:18%個(gè).
正在處理的任務(wù)任務(wù)名:鉆孔 工人名:徐虎 完成度:60% 完成度 完成度:60%個(gè).
正在處理的任務(wù)任務(wù)名:鏜孔 工人名:張秉貴 完成度:25% 完成度 完成度:25%個(gè).
正在處理的任務(wù)任務(wù)名:鑄造 工人名:王進(jìn)喜 完成度:0% 完成度 完成度:0%個(gè).
正在處理的任務(wù)任務(wù)名:拉槽 工人名:時(shí)傳詳 完成度:36% 完成度 完成度:36%個(gè).
正在處理的任務(wù)任務(wù)名:鉆孔 工人名:徐虎 完成度:90% 完成度 完成度:90%個(gè).
任務(wù)任務(wù)名:鉆孔 工人名:徐虎 完成度:100%處理完畢!
工人:徐虎取得任務(wù):校驗(yàn)
正在處理的任務(wù)任務(wù)名:鏜孔 工人名:張秉貴 完成度:30% 完成度 完成度:30%個(gè).
正在處理的任務(wù)任務(wù)名:鑄造 工人名:王進(jìn)喜 完成度:12% 完成度 完成度:12%個(gè).
正在處理的任務(wù)任務(wù)名:拉槽 工人名:時(shí)傳詳 完成度:54% 完成度 完成度:54%個(gè).
正在處理的任務(wù)任務(wù)名:校驗(yàn) 工人名:徐虎 完成度:0% 完成度 完成度:0%個(gè).
正在處理的任務(wù)任務(wù)名:鏜孔 工人名:張秉貴 完成度:35% 完成度 完成度:35%個(gè).
正在處理的任務(wù)任務(wù)名:鑄造 工人名:王進(jìn)喜 完成度:25% 完成度 完成度:25%個(gè).
正在處理的任務(wù)任務(wù)名:拉槽 工人名:時(shí)傳詳 完成度:72% 完成度 完成度:72%個(gè).
正在處理的任務(wù)任務(wù)名:校驗(yàn) 工人名:徐虎 完成度:33% 完成度 完成度:33%個(gè).
正在處理的任務(wù)任務(wù)名:鏜孔 工人名:張秉貴 完成度:40% 完成度 完成度:40%個(gè).
正在處理的任務(wù)任務(wù)名:鑄造 工人名:王進(jìn)喜 完成度:37% 完成度 完成度:37%個(gè).
正在處理的任務(wù)任務(wù)名:拉槽 工人名:時(shí)傳詳 完成度:90% 完成度 完成度:90%個(gè).
任務(wù)任務(wù)名:拉槽 工人名:時(shí)傳詳 完成度:100%處理完畢!
工人:時(shí)傳詳取得任務(wù):內(nèi)務(wù)
正在處理的任務(wù)任務(wù)名:校驗(yàn) 工人名:徐虎 完成度:66% 完成度 完成度:66%個(gè).
任務(wù)任務(wù)名:校驗(yàn) 工人名:徐虎 完成度:100%處理完畢!
任務(wù)告罄
工人:徐虎進(jìn)入閑置狀態(tài)
正在處理的任務(wù)任務(wù)名:鏜孔 工人名:張秉貴 完成度:45% 完成度 完成度:45%個(gè).
正在處理的任務(wù)任務(wù)名:鑄造 工人名:王進(jìn)喜 完成度:50% 完成度 完成度:50%個(gè).
正在處理的任務(wù)任務(wù)名:內(nèi)務(wù) 工人名:時(shí)傳詳 完成度:0% 完成度 完成度:0%個(gè).
正在處理的任務(wù)任務(wù)名:鏜孔 工人名:張秉貴 完成度:50% 完成度 完成度:50%個(gè).
正在處理的任務(wù)任務(wù)名:鑄造 工人名:王進(jìn)喜 完成度:62% 完成度 完成度:62%個(gè).
正在處理的任務(wù)任務(wù)名:內(nèi)務(wù) 工人名:時(shí)傳詳 完成度:20% 完成度 完成度:20%個(gè).
正在處理的任務(wù)任務(wù)名:鏜孔 工人名:張秉貴 完成度:55% 完成度 完成度:55%個(gè).
正在處理的任務(wù)任務(wù)名:鑄造 工人名:王進(jìn)喜 完成度:75% 完成度 完成度:75%個(gè).
正在處理的任務(wù)任務(wù)名:內(nèi)務(wù) 工人名:時(shí)傳詳 完成度:40% 完成度 完成度:40%個(gè).
正在處理的任務(wù)任務(wù)名:鏜孔 工人名:張秉貴 完成度:60% 完成度 完成度:60%個(gè).
正在處理的任務(wù)任務(wù)名:鑄造 工人名:王進(jìn)喜 完成度:87% 完成度 完成度:87%個(gè).
任務(wù)任務(wù)名:鑄造 工人名:王進(jìn)喜 完成度:100%處理完畢!
任務(wù)告罄
工人:王進(jìn)喜進(jìn)入閑置狀態(tài)
正在處理的任務(wù)任務(wù)名:內(nèi)務(wù) 工人名:時(shí)傳詳 完成度:60% 完成度 完成度:60%個(gè).
正在處理的任務(wù)任務(wù)名:鏜孔 工人名:張秉貴 完成度:65% 完成度 完成度:65%個(gè).
正在處理的任務(wù)任務(wù)名:內(nèi)務(wù) 工人名:時(shí)傳詳 完成度:80% 完成度 完成度:80%個(gè).
任務(wù)任務(wù)名:內(nèi)務(wù) 工人名:時(shí)傳詳 完成度:100%處理完畢!
任務(wù)告罄
工人:時(shí)傳詳進(jìn)入閑置狀態(tài)
正在處理的任務(wù)任務(wù)名:鏜孔 工人名:張秉貴 完成度:70% 完成度 完成度:70%個(gè).
正在處理的任務(wù)任務(wù)名:鏜孔 工人名:張秉貴 完成度:75% 完成度 完成度:75%個(gè).
正在處理的任務(wù)任務(wù)名:鏜孔 工人名:張秉貴 完成度:80% 完成度 完成度:80%個(gè).
正在處理的任務(wù)任務(wù)名:鏜孔 工人名:張秉貴 完成度:85% 完成度 完成度:85%個(gè).
正在處理的任務(wù)任務(wù)名:鏜孔 工人名:張秉貴 完成度:90% 完成度 完成度:90%個(gè).
正在處理的任務(wù)任務(wù)名:鏜孔 工人名:張秉貴 完成度:95% 完成度 完成度:95%個(gè).
任務(wù)任務(wù)名:鏜孔 工人名:張秉貴 完成度:100%處理完畢!
任務(wù)告罄
工人:張秉貴進(jìn)入閑置狀態(tài)

代碼下載:
http://m.tkk7.com/Files/sitinspring/AutoTask20071020100536.rar