日常編碼中,我們常需要為各種業務進行建模,為工廠中的任務調度建模就很有意思的,它的主要流程是基本是這樣:
1.調度員將工件圖紙交付給工人,這是任務的下達.
2.工人工作,完成工件,這是任務的進行過程.
3.工件完成后,工人將圖紙和工件返還給調度員,或者到了確定的時間后由調度員去取.這是任務的完成.
4.重復上述三個步驟.
在這個流程中,還存在一些特征:
1.工人可以有多項任務,但他在一個時間只能做一個活,具體做那個由任務的優先級確定.
2.任務完成后要讓調度員知道,現實中是工人來找調度員或者調度員找工人來實現的.一般來說調度員找工人的情況居多.
從上述情況分析,我們需要任務,工人,調度員三個類來完成建模,另外為了方便任務的存儲和管理,還需要一個任務串類來輔助.
首先看任務類,除了Id,name這樣的常規屬性外,它應該具有下面的成員:
1.完成所需要的總工時數.
2.已經完成的工時數,它和總工時數的比值就是完成比例.
3.優先級.
4.任務接受者,也就是工人.
5.任務發布者,也就是調度員.
它還應該具有一個重要函數,這個函數應該是定時被執行的,執行時先增加已經完成的工時數,然后看是否完成,是則把自己從任務接受者的待完成任務鏈表中刪除,再添加到任務發布者的已完成任務鏈表中去.
具體代碼如下:
package com.sitinspring.taskmanagement.domain;

import com.sitinspring.taskmanagement.util.IdUtil;


public class Task implements Comparable
{
private String id;

private String name;

// 完成需消耗的工時數
private int manHour;

// 已經完成的工時數
private int completed;

// 優先級
private int priority;

// 接受任務者
private Worker worker;

// 發布任務者
private Attemper attemper;


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;
}

// 任務是否完成

public boolean isCompleted()
{
return completed >= manHour;
}

// 添加完成度

public void addCompleted(int n)
{
completed += n;


if (isCompleted())
{
completed = manHour;


if (worker != null)
{
// 完成后讓工人把自己從任務列表中刪除
worker.removeTask(this);
}


if (attemper != null)
{
// 完成后把任務添加到調度員(任務發送者)的完成任務鏈表
attemper.addCompletedTask(this);
}
}
}


public int compareTo(Object obj)
{
Task another = (Task) obj;
return (another.priority) - this.priority;
}


public String toString()
{
return "任務名:" + name + " 工人名:" + worker.getName() + " 完成度:" + completed
* 100 / manHour + "%";
}


public int getCompleted()
{
return completed;
}


public void setCompleted(int completed)
{
this.completed = completed;
}


public int getManHour()
{
return manHour;
}


public void setManHour(int manHour)
{
this.manHour = manHour;
}


public String getName()
{
return name;
}


public void setName(String name)
{
this.name = name;
}


public String getId()
{
return id;
}


public int getPriority()
{
return priority;
}


public void setPriority(int priority)
{
this.priority = priority;
}


public Worker getWorker()
{
return worker;
}


public void setWorker(Worker worker)
{
this.worker = worker;
}


public Attemper getAttemper()
{
return attemper;
}


public void setAttemper(Attemper attemper)
{
this.attemper = attemper;
}
}
其次再來看任務串類,它用于管理多個任務,自然它必定具有一個鏈表成員,類中大部分函數都是圍繞這個成員設計的,另外考慮到工人需要取得最優先的任務,鏈表需要按任務的優先級排序,然后做一個函數用于取得最開頭的任務即優先級最高的任務.isCompleted函數用于判斷所有任務是否完成.
代碼如下:
package com.sitinspring.taskmanagement.domain;

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


public class TaskBunch
{
// 任務鏈表
private List<Task> tasks;

public TaskBunch()
{
tasks=new LinkedList<Task>();
}
// 取得最優先任務

public Task getTopTask()
{
return tasks.get(0);
}
// 取得任務個數

public int getSize()
{
return tasks.size();
}
// 判斷是否完成

public boolean isCompleted()
{

for(Task task:tasks)
{

if(task.isCompleted()==false)
{
return false;
}
}
return true;
}
// 添加任務

public void addTask(Task task)
{
tasks.add(task);
Collections.sort(tasks);
}
// 刪除任務

public void removeTask(Task task)
{
tasks.remove(task);
}
}
接下來是工人類,它有一個任務串成員用于存儲待完成任務,由于它需要定時執行任務,因此需要實現Runnable接口,在run函數中處理任務,另外再做一個doWork()讓線程工作起來.工作時首先取得待完成任務鏈表中的優先級最高的任務,執行任務中的addCompleted方法,如果待完成任務一直沒完的話就不斷的執行,直到所有任務完成為止.至于任務完成后的從自己的待完成任務鏈表中刪除及添加到調度員的已完成任務鏈表中的工作由任務自己完成,工人無需管理,具體請看Task類的addCompleted方法.
run函數中,sleep的1000毫秒當一個小時看,這里工人基本是當24小時的班,即機器不閑著人三班倒,如果是日常的八小時任務則可以先取一下當前時間是否在工作時間內,是則繼續干,如果不是應該加入繼續休眠sleep的代碼.
工人類代碼如下:
package com.sitinspring.taskmanagement.domain;

import com.sitinspring.taskmanagement.util.IdUtil;


public class Worker implements Runnable
{
private String id;
private String name;
// 任務列表
private TaskBunch taskBunch;
// 工作速度
private int speed;

public Worker(String name,int speed)
{
id=IdUtil.generateId();
this.name=name;
this.speed=speed;
taskBunch=new TaskBunch();
}
// 添加任務

public void addTask(Task task)
{
task.setWorker(this);
taskBunch.addTask(task);
}
// 刪除任務

public void removeTask(Task task)
{
taskBunch.removeTask(task);
}
// 開始干活

public void doWork()
{
Thread thread=new Thread(this);
thread.start();
}
// 真正干活

public void run()
{

while(!taskBunch.isCompleted())
{

try
{
Thread.sleep(1000);
Task task=taskBunch.getTopTask();
task.addCompleted(speed);
System.out.println("正在處理的任務"+task+" 還需處理"+taskBunch.getSize()+"個.");
}

catch(Exception ex)
{
ex.printStackTrace();
}
}
System.out.println("工人"+name+"的全部任務處理完畢!");
}

public String getName()
{
return name;
}

public void setName(String name)
{
this.name = name;
}

public String getId()
{
return id;
}
}
最后是調度員類,它的主要任務是生成任務以及管理已經完成的任務,代碼比較簡單:
package com.sitinspring.taskmanagement.domain;

import com.sitinspring.taskmanagement.util.IdUtil;


public class Attemper
{
private String id;
private String name;
private TaskBunch completedTasks;

public Attemper(String name)
{
id=IdUtil.generateId();
this.name=name;
completedTasks=new TaskBunch();
}

public Task generateTask(String name,int manHour,int priority)
{
Task task=new Task(name,manHour,priority);
task.setAttemper(this);
return task;
}

public void addCompletedTask(Task task)
{
completedTasks.addTask(task);
}


public String getId()
{
return id;
}


public String getName()
{
return name;
}
}
具體示例執行過程如下:
Attemper Attemper=new Attemper("調度員");
Worker commonWorker=new Worker("普通工人一",2);
commonWorker.addTask(Attemper.generateTask("任務1",8,1));
commonWorker.addTask(Attemper.generateTask("任務2",9,2));
commonWorker.addTask(Attemper.generateTask("任務3",20,3));
commonWorker.doWork();
Worker skilledWorker=new Worker("熟練工人二",3);
skilledWorker.addTask(Attemper.generateTask("任務4",5,2));
skilledWorker.addTask(Attemper.generateTask("任務5",30,2));
skilledWorker.addTask(Attemper.generateTask("任務6",16,3));
skilledWorker.doWork();
Worker oldSkilledWorker=new Worker("老熟練工人三",5);
oldSkilledWorker.addTask(Attemper.generateTask("任務7",15,2));
oldSkilledWorker.addTask(Attemper.generateTask("任務8",13,2));
oldSkilledWorker.addTask(Attemper.generateTask("任務9",7,3));
oldSkilledWorker.doWork();
執行輸出如下:
正在處理的任務任務名:任務3 工人名:普通工人一 完成度:10% 還需處理3個.
正在處理的任務任務名:任務6 工人名:熟練工人二 完成度:18% 還需處理3個.
正在處理的任務任務名:任務9 工人名:老熟練工人三 完成度:71% 還需處理3個.
正在處理的任務任務名:任務3 工人名:普通工人一 完成度:20% 還需處理3個.
正在處理的任務任務名:任務6 工人名:熟練工人二 完成度:37% 還需處理3個.
正在處理的任務任務名:任務9 工人名:老熟練工人三 完成度:100% 還需處理2個.
正在處理的任務任務名:任務3 工人名:普通工人一 完成度:30% 還需處理3個.
正在處理的任務任務名:任務6 工人名:熟練工人二 完成度:56% 還需處理3個.
正在處理的任務任務名:任務7 工人名:老熟練工人三 完成度:33% 還需處理2個.
正在處理的任務任務名:任務3 工人名:普通工人一 完成度:40% 還需處理3個.
正在處理的任務任務名:任務6 工人名:熟練工人二 完成度:75% 還需處理3個.
正在處理的任務任務名:任務7 工人名:老熟練工人三 完成度:66% 還需處理2個.
正在處理的任務任務名:任務3 工人名:普通工人一 完成度:50% 還需處理3個.
正在處理的任務任務名:任務6 工人名:熟練工人二 完成度:93% 還需處理3個.
正在處理的任務任務名:任務7 工人名:老熟練工人三 完成度:100% 還需處理1個.
正在處理的任務任務名:任務3 工人名:普通工人一 完成度:60% 還需處理3個.
正在處理的任務任務名:任務6 工人名:熟練工人二 完成度:100% 還需處理2個.
正在處理的任務任務名:任務8 工人名:老熟練工人三 完成度:38% 還需處理1個.
正在處理的任務任務名:任務3 工人名:普通工人一 完成度:70% 還需處理3個.
正在處理的任務任務名:任務4 工人名:熟練工人二 完成度:60% 還需處理2個.
正在處理的任務任務名:任務8 工人名:老熟練工人三 完成度:76% 還需處理1個.
正在處理的任務任務名:任務3 工人名:普通工人一 完成度:80% 還需處理3個.
正在處理的任務任務名:任務4 工人名:熟練工人二 完成度:100% 還需處理1個.
正在處理的任務任務名:任務8 工人名:老熟練工人三 完成度:100% 還需處理0個.
工人老熟練工人三的全部任務處理完畢!
正在處理的任務任務名:任務3 工人名:普通工人一 完成度:90% 還需處理3個.
正在處理的任務任務名:任務5 工人名:熟練工人二 完成度:10% 還需處理1個.
正在處理的任務任務名:任務3 工人名:普通工人一 完成度:100% 還需處理2個.
正在處理的任務任務名:任務5 工人名:熟練工人二 完成度:20% 還需處理1個.
正在處理的任務任務名:任務2 工人名:普通工人一 完成度:22% 還需處理2個.
正在處理的任務任務名:任務5 工人名:熟練工人二 完成度:30% 還需處理1個.
正在處理的任務任務名:任務2 工人名:普通工人一 完成度:44% 還需處理2個.
正在處理的任務任務名:任務5 工人名:熟練工人二 完成度:40% 還需處理1個.
正在處理的任務任務名:任務2 工人名:普通工人一 完成度:66% 還需處理2個.
正在處理的任務任務名:任務5 工人名:熟練工人二 完成度:50% 還需處理1個.
正在處理的任務任務名:任務2 工人名:普通工人一 完成度:88% 還需處理2個.
正在處理的任務任務名:任務5 工人名:熟練工人二 完成度:60% 還需處理1個.
正在處理的任務任務名:任務2 工人名:普通工人一 完成度:100% 還需處理1個.
正在處理的任務任務名:任務5 工人名:熟練工人二 完成度:70% 還需處理1個.
正在處理的任務任務名:任務1 工人名:普通工人一 完成度:25% 還需處理1個.
正在處理的任務任務名:任務5 工人名:熟練工人二 完成度:80% 還需處理1個.
正在處理的任務任務名:任務1 工人名:普通工人一 完成度:50% 還需處理1個.
正在處理的任務任務名:任務5 工人名:熟練工人二 完成度:90% 還需處理1個.
正在處理的任務任務名:任務1 工人名:普通工人一 完成度:75% 還需處理1個.
正在處理的任務任務名:任務5 工人名:熟練工人二 完成度:100% 還需處理0個.
工人熟練工人二的全部任務處理完畢!
正在處理的任務任務名:任務1 工人名:普通工人一 完成度:100% 還需處理0個.
工人普通工人一的全部任務處理完畢!

代碼下載:
http://www.tkk7.com/Files/sitinspring/TaskManagement20071005131809.rar
以上.