和風細雨

          世上本無難事,心以為難,斯乃真難。茍不存一難之見于心,則運用之術自出。

          線程調度實例

          本文內容

          本文將從一個現實例子來實際說明線程調度方法wait,notify和notifyAll的使用。

          工廠中任務的領受和執行

          某工廠執行這樣的機制:當生產任務下達到車間時會統一放在一個地方,由工人們來取活。
          工人取活如此執行:一個工人手頭只能有一個活,如果沒做完不能做下一個,如果做完了則可以到公共的地方去取一個;如果沒有活可取則閑著直到來活為止。

          本文就是講述怎樣使用線程的調度三方法wait,notify和notifyAll來實現這一現實活動的。

          任務類Task-它用來實現一個”活”,其中關鍵的成員是完成需消耗的工時數manHour和已經完成的工時數completed

          public class Task implements Comparable {
            private String id;

            private String name;

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

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

            // 優先級
            private int priority;

            // 接受任務者
            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;
            }
           // 任務是否完成
            public boolean isCompleted() {
              return completed >= manHour;
            }

            // 添加完成度
            public void addCompleted(int n) {
              completed += n;

              if (isCompleted()) {
                completed = manHour;

                if (worker != null) {
                  System.out.println("任務"+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 String getCompletedRatio() {
              return " 完成度:" + completed * 100 / manHour + "%";
            }
          ...getter/setter方法省略..

          }

          任務庫類TaskLibrary

          這個類對應現實中的取活的地方,每個活Task放在這個類的成員tasks中,有兩個方法來添加單個任務和多個任務,還有一個fetchTask方法來供工人領受任務.

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

          工人類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("正在處理的任務" + currTask + " 完成度"
                      + currTask.getCompletedRatio() + "個.");
                  currTask.addCompleted(speed);
                } catch (Exception ex) {
                  ex.printStackTrace();
                }
              }
            }
          。。。
          }

          運行代碼

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

          運行情況分析

          一開始先初始化任務庫,然后進行給任務庫中添加任務,初始化工人實例時會把任務庫實例的地址傳入,工人實例初始化完畢后會調用doWork函數去任務庫取任務開始做,這會進入TaskLibrary類的fetchTask函數,這時如果沒有則會讓工人等待,有則把第一個任務給他,然后周而復始進行這一過程.

          運行結果示例

           工人:王進喜取得任務:培訓 工人:時傳詳取得任務:鍛造 工人:張秉貴取得任務:打磨 工人:徐虎取得任務:車階梯 正在處理的任務任務名:培訓 工人名:王進喜 完成度: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%處理完畢! 工人:徐虎取得任務:鉆孔

           

          posted on 2008-02-22 14:17 和風細雨 閱讀(325) 評論(0)  編輯  收藏 所屬分類: 線程

          主站蜘蛛池模板: 罗甸县| 雅江县| 黔东| 连平县| 台前县| 连州市| 星座| 塔城市| 宜丰县| 织金县| 克拉玛依市| 保山市| 泸水县| 东乡| 明溪县| 富阳市| 涪陵区| 忻城县| 阿坝县| 信丰县| 宜阳县| 顺昌县| 滨海县| 宁河县| 丹江口市| 安福县| 庄浪县| 汤阴县| 泊头市| 衡山县| 天祝| 鱼台县| 巴里| 麻城市| 包头市| 鄱阳县| 托克逊县| 祁阳县| 普定县| 灵石县| 龙泉市|