本文內(nèi)容
本文將從一個(gè)現(xiàn)實(shí)例子來實(shí)際說明線程調(diào)度方法wait,notify和notifyAll的使用。
工廠中任務(wù)的領(lǐng)受和執(zhí)行
某工廠執(zhí)行這樣的機(jī)制:當(dāng)生產(chǎn)任務(wù)下達(dá)到車間時(shí)會(huì)統(tǒng)一放在一個(gè)地方,由工人們來取活。
工人取活如此執(zhí)行:一個(gè)工人手頭只能有一個(gè)活,如果沒做完不能做下一個(gè),如果做完了則可以到公共的地方去取一個(gè);如果沒有活可取則閑著直到來活為止。
本文就是講述怎樣使用線程的調(diào)度三方法wait,notify和notifyAll來實(shí)現(xiàn)這一現(xiàn)實(shí)活動(dòng)的。
任務(wù)類Task-它用來實(shí)現(xiàn)一個(gè)”活”,其中關(guān)鍵的成員是完成需消耗的工時(shí)數(shù)manHour和已經(jīng)完成的工時(shí)數(shù)completed
public class Task implements Comparable {
private String id;
private String name;
// 完成需消耗的工時(shí)數(shù)
private int manHour;
// 已經(jīng)完成的工時(shí)數(shù)
private int completed;
// 優(yōu)先級(jí)
private int priority;
// 接受任務(wù)者
private Worker worker;
public Task(String name, int manHour) {
this(name, manHour, 0);
}
public Task(String name, int manHour, int priority) {
id = IdUtil.generateId();
this.name = name;
this.manHour = manHour;
this.priority = priority;
this.completed = 0;
}
// 任務(wù)是否完成
public boolean isCompleted() {
return completed >= manHour;
}
// 添加完成度
public void addCompleted(int n) {
completed += n;
if (isCompleted()) {
completed = manHour;
if (worker != null) {
System.out.println("任務(wù)"+this+"處理完畢!");
}
}
}
public int compareTo(Object obj) {
Task another = (Task) obj;
return (another.priority) - this.priority;
}
public String toString() {
return "任務(wù)名:" + name + " 工人名:" + worker.getName() + " 完成度:" + completed
* 100 / manHour + "%";
}
public String getCompletedRatio() {
return " 完成度:" + completed * 100 / manHour + "%";
}
...getter/setter方法省略..
}
任務(wù)庫(kù)類TaskLibrary
這個(gè)類對(duì)應(yīng)現(xiàn)實(shí)中的取活的地方,每個(gè)活Task放在這個(gè)類的成員tasks中,有兩個(gè)方法來添加單個(gè)任務(wù)和多個(gè)任務(wù),還有一個(gè)fetchTask方法來供工人領(lǐng)受任務(wù).
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;
}
}
工人類Worker
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("正在處理的任務(wù)" + currTask + " 完成度"
+ currTask.getCompletedRatio() + "個(gè).");
currTask.addCompleted(speed);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
。。。
}
運(yùn)行代碼
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);
運(yùn)行情況分析
一開始先初始化任務(wù)庫(kù),然后進(jìn)行給任務(wù)庫(kù)中添加任務(wù),初始化工人實(shí)例時(shí)會(huì)把任務(wù)庫(kù)實(shí)例的地址傳入,工人實(shí)例初始化完畢后會(huì)調(diào)用doWork函數(shù)去任務(wù)庫(kù)取任務(wù)開始做,這會(huì)進(jìn)入TaskLibrary類的fetchTask函數(shù),這時(shí)如果沒有則會(huì)讓工人等待,有則把第一個(gè)任務(wù)給他,然后周而復(fù)始進(jìn)行這一過程.
運(yùn)行結(jié)果示例
工人:王進(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ù):鉆孔