流水调度作业:
n个作业{0,1,2,…,n}在2台机器上M1和M2组成的流水线上完成加工。
每个作业加工的顺序都是先在M1上加工,后在M2上加工.
Johnson算法:
( 作业在M1和M2上的时间分别为a,b)
把需要加工的作业分成两个集合,N1,N2;
1. N1中所有元素a<b,按照a升序排序;
2. N2中所有元素a>=b,按照b降序排序;
3. N1,N2合并得到执行最优执行顺序
(数学推倒找度娘)
举个栗子:
一组作业:[{1,3},{4,2},{5,4},{6,3},{5,6},{3,4}]
({1,3}表示在M1机器上作业时间为1,在M2机器上的时间为3)
N1:[{1,3},{3,4},{5,6}]
N2:[{5,4},{6,3},{4,2}]
因此执行顺序为:[{1,3},{3,4},{5,6},{5,4},{6,3},{4,2}]
总时间:
如图所示:
绿色表示在M1中执行的时间,蓝色表示在M2中执行的时间;
由图可知:总时间=M2等待时间+M2执行时间
total=1+3+4+1+6+4+1+3+1+2=26
解:
M1上执行的总时间为:suma;
M2上执行的总时间为sumb
初始化:suma=a1;sumb=a1;
循环遍历数组:
for(int i=1;i<length;i++){
suma = suma+array[i].a;
sumb = sumb +array[i-1].b;
//比较suma与sumb,如果sumb<suma,说明有等待时间
if(sumb<suma)
sumb = suma-sumb+sumb;//等待时间加M2执行时间
}
最后sumb = sumb+array[length-1].b;//循环里少加了最后一个作业在M2执行的时间,需要加上
java代码实现:
package com.util.ist;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
/**
* @author zbc
*jdk需要1.8
*/
public class Liushui {
public static void main(String[] args) {
Node[] nodes = { new Node(1, 3), new Node(3, 4), new Node(5, 6), new Node(5, 4), new Node(6, 3),
new Node(4, 2) };
List<Node> list1 = new ArrayList<Node>();// list1中所有元素first<second,按照a升序排序;
List<Node> list2 = new ArrayList<Node>();// list2中所有元素first>=second,按照a升序排序;
for (Node n : nodes)
if (n.getFirst() < n.getSecond())
list1.add(n);//first<second
else
list2.add(n);//first>=second,
list1.sort(Comparator.comparing(Node::getFirst));//list1按照first升序排序
list2.sort(Comparator.comparing(Node::getSecond, (a,b)->b-a));//list1按照second降序排序
List<Node> list = new ArrayList<Node>(list1);//最优调度顺序
list.addAll(list2);
int suma = list.get(0).getFirst();
int sumb =list.get(0).getFirst();
for(int i=1;i<list.size();i++) {
int a = list.get(i).getFirst();
suma += a;
int b = list.get(i-1).getSecond();
sumb += b;
if(suma>sumb)// suma>sumb,说明有等待时间
sumb = suma; //sumb = suma-sumb+sumb;(等待时间+M2执行时间)
}
sumb += list.get(list.size()-1).getSecond();//循环里少加了最后一个作业在M2执行的时间,需要加上
System.out.print("原顺序为:[");
for(Node n : nodes)
System.out.print("{"+n.getFirst()+","+n.getSecond()+"}");
System.out.println("]");
System.out.print("N1:[");
for(Node n : list1)
System.out.print(n);
System.out.println("]");
System.out.print("N2:[");
for(Node n : list2)
System.out.print(n);
System.out.println("]");
System.out.print("最优调度执行顺序为:[");
for(Node n : list)
System.out.print(n);
System.out.println("]");
System.out.println("最优调度时间为:"+sumb);
}
}
//用来保存键值对
class Node {
private int first;
private int second;
public Node(int first, int second) {
this.first = first;
this.second = second;
}
public int getFirst() {
return first;
}
public void setFirst(int first) {
this.first = first;
}
public int getSecond() {
return second;
}
public void setSecond(int second) {
this.second = second;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "{"+this.first+","+this.second+"}";
}
}
输出:
原顺序为:[{1,3}{3,4}{5,6}{5,4}{6,3}{4,2}]
N1:[{1,3}{3,4}{5,6}]
N2:[{5,4}{6,3}{4,2}]
最优调度执行顺序为:[{1,3}{3,4}{5,6}{5,4}{6,3}{4,2}]
最优调度时间为:26