/******************************/ /* 複雑な待ち行列問題 */ /* coded by Y.Suganuma */ /******************************/ import java.io.*; import java.util.*; public class Test { /****************/ /* main program */ /****************/ public static void main(String args[]) throws IOException { BufferedReader inp = new BufferedReader(new InputStreamReader(System.in)); // 入り口 System.out.print("入り口(Inlet)の数は? "); int n_i = Integer.parseInt(inp.readLine().trim()); ArrayList <Inlet> inl = new ArrayList <Inlet>(); for (int i1 = 0; i1 < n_i; i1++) { double m_a = 0.0; System.out.print((i1+1) + " 番目の入り口(Inlet)\n"); System.out.print(" 名前は? "); String name1 = (inp.readLine()).trim(); ArrayDeque <Double> que = new ArrayDeque <Double>(); System.out.print(" 到着分布(=0:指数分布,1=一定時間間隔,<0:指定:客数の負値))? "); int n = Integer.parseInt(inp.readLine().trim()); if (n == 0) { System.out.print(" 到着時間間隔の平均値は? "); m_a = Double.parseDouble(inp.readLine().trim()); } else if (n == 1) { System.out.print(" 到着時間間隔は? "); m_a = Double.parseDouble(inp.readLine().trim()); } else { double x; for (int i2 = 0; i2 < -n; i2++) { System.out.print(" 到着時間は? "); x = Double.parseDouble(inp.readLine().trim()); que.add(x); } } System.out.print(" 並ぶ待ち行列の名前は? "); String name2 = (inp.readLine()).trim(); Inlet inl_e = new Inlet(name1, n, m_a, que, name2); inl.add(inl_e); } // 待ち行列 System.out.print("待ち行列(Queue)の数は? "); int n_q = Integer.parseInt(inp.readLine().trim()); ArrayList <Queue> que = new ArrayList <Queue>(); for (int i1 = 0; i1 < n_q; i1++) { System.out.print((i1+1) + " 番目の待ち行列(Queue)\n"); System.out.print(" 名前は? "); String name1 = (inp.readLine()).trim(); System.out.print(" 入り口(0),または,窓口(n>0,窓口の数)から? "); int n = Integer.parseInt(inp.readLine().trim()); ArrayList <String> in = new ArrayList <String>(); if (n == 0) { System.out.print(" 入り口の名前は? "); String name2 = (inp.readLine()).trim(); in.add(name2); } else { for (int i2 = 0; i2 < n; i2++) { System.out.print(" " + (i2+1) + " 番目の窓口の名前は? "); String name3 = (inp.readLine()).trim(); in.add(name3); } } int m; System.out.print(" 処理する窓口の数は? "); m = Integer.parseInt(inp.readLine().trim()); ArrayList <String> out = new ArrayList <String>(); for (int i2 = 0; i2 < m; i2++) { System.out.print(" " + (i2+1) + " 番目の窓口の名前は? "); String name4 = (inp.readLine()).trim(); out.add(name4); } Queue que_e = new Queue(name1, n, in, m, out); que.add(que_e); } // 窓口 System.out.print("窓口(Entity)の数は? "); int n_e = Integer.parseInt(inp.readLine().trim()); ArrayList <Entity> ent = new ArrayList <Entity>(); for (int i1 = 0; i1 < n_e; i1++) { double m_s = 0.0; System.out.print((i1+1) + " 番目の窓口(Entity)\n"); System.out.print(" 名前は? "); String name1 = (inp.readLine()).trim(); System.out.print(" サービス分布(=0:指数分布,1=一定時間)? "); int s_t = Integer.parseInt(inp.readLine().trim()); if (s_t == 0) { System.out.print(" サービス時間の平均値は? "); m_s = Double.parseDouble(inp.readLine().trim()); } else { System.out.print(" サービス時間は? "); m_s = Double.parseDouble(inp.readLine().trim()); } System.out.print(" 待ち行列(入力)の名前は? "); String name2 = (inp.readLine()).trim(); int sw; System.out.print(" 終了後,外部(0),または,待ち行列(1)? "); sw = Integer.parseInt(inp.readLine().trim()); String name3 = ""; if (sw > 0) { System.out.print(" 待ち行列(出力)の名前は? "); name3 = (inp.readLine()).trim(); } Entity ent_e = new Entity(name1, s_t, m_s, name2, sw, name3); ent.add(ent_e); } // 全体の制御を行うクラス double end; System.out.print("シミュレーション終了時間? "); end = Double.parseDouble(inp.readLine().trim()); Q_base base = new Q_base(inl, que, ent, end); // 全体の制御を行うクラス // 実行 base.Control(); // 出力 base.Output(); } } /*********************/ /* クラスInletの定義 */ /*********************/ class Inlet { String name; // 入り口名 String out; // 待ち行列名 int out_n; // 待ち行列番号 double arrive_time; // 客の到着時刻(負:客がない) int a_t; // = -n : 到着する客の人数を負の値にしたもの // =0 : 指数分布 // =1 : 一定時間間隔 double mean; // 到着時間間隔またはその平均 ArrayDeque <Double> que; // 客の到着時刻リスト /*************************************************************/ /* コンストラクタ */ /* name1 : 入り口名 */ /* a_t1; // = -n : 到着する客の人数を負の値にしたもの */ /* // =0 : 指数分布 */ /* // =1 : 一定時間間隔 */ /* m_a: 到着時間間隔またはその平均 */ /* que1 : 客の到着時刻リスト */ /* name2 : 待ち行列名 */ /*************************************************************/ Inlet (String name1, int a_t1, double m_a, ArrayDeque<Double> que1, String name2) { name = name1; out = name2; mean = m_a; a_t = a_t1; que = que1; if (a_t == 1) arrive_time = 0; else if (a_t < 0) arrive_time = que.pollFirst().doubleValue(); } } /*********************/ /* クラスQueueの定義 */ /*********************/ class Queue { String name; // 待ち行列名 int nc; // 待ち行列への到着客数カウンタ int max_q_l; // 最大待ち行列長 double c_ql; // 待ち行列長にその長さが継続した時間を乗じた値の累計 double ql_t; // 現在の待ち行列長になった時間 double max_wt; // 最大待ち時間 double c_wt; // 待ち時間の累計 int n; // =0 : 入り口から入る // >0 : 複数の窓口から入る(窓口数) ArrayList <String> in; // 入り口名,または,窓口名 ArrayList <Integer> in_n; // 入り口番号,または,窓口番号 int m; // 処理する窓口数 ArrayList <String> out; // 窓口名 ArrayList <Integer> out_n; // 窓口番号 ArrayDeque <Integer> que; // 待ち行列 /*********************************************/ /* コンストラクタ */ /* name1 : 待ち行列名 */ /* n1 : =0 : 入り口から入る */ /* >0 : 複数の窓口から入る(窓口数) */ /* in1 : 入り口名,または,窓口名 */ /* m1 : 処理する窓口数 */ /* out1 : 窓口名 */ /*********************************************/ Queue(String name1, int n1, ArrayList<String> in1, int m1, ArrayList<String> out1) { name = name1; in = in1; n = n1; in_n = new ArrayList <Integer>(); out = out1; m = m1; out_n = new ArrayList <Integer>(); que = new ArrayDeque <Integer>(); nc = 0; max_q_l = 0; c_ql = 0.0; ql_t = 0.0; max_wt = 0.0; c_wt = 0.0; } } /**********************/ /* クラスEntityの定義 */ /**********************/ class Entity { String name; // Entity名 double busy_t; // 窓口がふさがった時間 double c_busy; // 窓口がふさがっている時間の累計 double end_time; // サービス終了時間(負:何も処理していない) int s_t; // =0 : 指数分布 // =1 : 一定時間 double mean; // 平均サービス時間 int service; // サービス中の客番号(0のときはなし) String in; // 待ち行列(入力)の名前 int in_n; // 待ち行列(入力)番号 int to; // =0 : システムの外に出る // =1 : 待ち行列に入る String out; // 待ち行列(出力)の名前 int out_n; // 待ち行列(出力)番号 /****************************************/ /* コンストラクタ */ /* name1 : 窓口名 */ /* s_t1; // =0 : 指数分布 */ /* // =1 : 一定時間 */ /* m_s:サービス時間またはその平均 */ /* in : 待ち行列(入力)の名前 */ /* sw : =0 : システムの外に出る */ /* =1 : 待ち行列に入る */ /* out : 待ち行列(出力)の名前 */ /****************************************/ Entity(String name1, int s_t1, double m_s, String name2, int sw, String name3) { name = name1; to = sw; in = name2; if (to > 0) out = name3; end_time = -1.0; s_t = s_t1; mean = m_s; service = 0; busy_t = -1.0; c_busy = 0.0; } } /************************/ /* クラスCustomerの定義 */ /************************/ class Customer { double time; // 到着時刻 int state1; // 客の状態1 // =0 : 待ち行列に入っている // =1 : サービスを受けている int state2; // 客の状態2(待ち行列番号,または,窓口番号) /*********************/ /* コンストラクタ */ /* s1,s2 : 状態 */ /* t : 到着時刻 */ /*******************************/ Customer(int s1, int s2, double t) { time = t; state1 = s1; state2 = s2; } } /**********************/ /* クラスQ_baseの定義 */ /**********************/ class Q_base { private String name; // システム名 private double p_time; // 現在時刻 private int max_c; // 最大系内客数 private int nc; // 到着客数カウンタ private double now_c_t; // 現在の系内客数になった時間 private double c_now_c; // 系内客数にその数が継続した時間を乗じた値の累計 private double c_sys; // 滞在時間の累計 private double max_sys; // 最大滞在時間 private double end; // シミュレーション終了時間 private Random rn; // 乱数 private TreeMap <Integer, Customer> cus; // 系内にいる客のリスト private ArrayList <Inlet> inl; // Inletオブジェクトリスト private ArrayList <Queue> que; // Queueオブジェクトリスト private ArrayList <Entity> ent; // Entityオブジェクトリスト /***************************************/ /* コンストラクタ */ /* v_i : Inletオブジェクトリスト */ /* v_q : Queueオブジェクトリスト */ /* v_e : Entityオブジェクトリスト */ /* e : シミュレーション終了時刻 */ /***************************************/ Q_base(ArrayList<Inlet> v_i, ArrayList<Queue> v_q, ArrayList<Entity> v_e, double e) { // 接続関係のチェック System.out.println(); // Inlet inl = v_i; que = v_q; ent = v_e; for (int i1 = 0; i1 < inl.size()-1; i1++) { for (int i2 = i1+1; i2 < inl.size(); i2++) { if (inl.get(i1).name.equals(inl.get(i2).name)) { System.out.println("***error 同じ名前の入り口があります " + inl.get(i1).name); System.exit(1); } } } int k; for (int i1 = 0; i1 < inl.size(); i1++) { k = -1; for (int i2 = 0; i2 < que.size(); i2++) { if (inl.get(i1).out.equals(que.get(i2).name)) { k = i2; break; } } if (k >= 0) inl.get(i1).out_n = k; else { System.out.println("***error 入り口から入る待ち行列名が不適当です " + inl.get(i1).out); System.exit(1); } } // Queue for (int i1 = 0; i1 < que.size()-1; i1++) { for (int i2 = i1+1; i2 < que.size(); i2++) { if (que.get(i1).name.equals(que.get(i2).name)) { System.out.println("***error 同じ名前の待ち行列があります " + que.get(i1).name); System.exit(1); } } } for (int i1 = 0; i1 < que.size(); i1++) { if (que.get(i1).n == 0) { k = -1; for (int i2 = 0; i2 < inl.size(); i2++) { if (que.get(i1).in.get(0).equals(inl.get(i2).name)) { k = i2; break; } } if (k >= 0) que.get(i1).in_n.add(new Integer(k)); else { System.out.println("***error 待ち行列に入る入り口名が不適当です " + que.get(i1).in.get(0)); System.exit(1); } } else { for (int i2 = 0; i2 < que.get(i1).n; i2++) { k = -1; for (int i3 = 0; i3 < ent.size(); i3++) { if (que.get(i1).in.get(i2).equals(ent.get(i3).name)) { k = i3; break; } } if (k >= 0) que.get(i1).in_n.add(new Integer(k)); else { System.out.println("***error 待ち行列に入る窓口名が不適当です " + que.get(i1).in.get(i2)); System.exit(1); } } } for (int i2 = 0; i2 < que.get(i1).m; i2++) { k = -1; for (int i3 = 0; i3 < ent.size(); i3++) { if (que.get(i1).out.get(i2).equals(ent.get(i3).name)) { k = i3; break; } } if (k >= 0) que.get(i1).out_n.add(new Integer(k)); else { System.out.println("***error 待ち行列を処理する窓口名が不適当です " + que.get(i1).out.get(i2)); System.exit(1); } } } // Entity for (int i1 = 0; i1 < ent.size()-1; i1++) { k = -1; for (int i2 = i1+1; i2 < ent.size(); i2++) { if (ent.get(i1).name.equals(ent.get(i2).name)) { System.out.println("***error 同じ名前の窓口があります " + ent.get(i1).name); System.exit(1); } } } for (int i1 = 0; i1 < ent.size(); i1++) { k = -1; for (int i2 = 0; i2 < que.size(); i2++) { if (ent.get(i1).in.equals(que.get(i2).name)) { k = i2; break; } } if (k >= 0) ent.get(i1).in_n = k; else { System.out.println("***error 窓口に入る待ち行列名が不適当です " + ent.get(i1).in); System.exit(1); } if (ent.get(i1).to > 0) { k = -1; for (int i2 = 0; i2 < que.size(); i2++) { if (ent.get(i1).out.equals(que.get(i2).name)) { k = i2; break; } } if (k >= 0) ent.get(i1).out_n = k; else { System.out.println("***error 窓口の出口にある待ち行列名が不適当です " + ent.get(i1).out); System.exit(1); } } } // 初期設定 cus = new TreeMap <Integer, Customer>(); p_time = 0.0; max_c = 0; nc = 0; now_c_t = 0.0; c_now_c = 0.0; c_sys = 0.0; max_sys = 0.0; end = e; // 乱数の初期設定 rn = new Random(); } /**********************/ /* 指数分布乱数の発生 */ /* m : 平均値 */ /* rerutn : 乱数 */ /**********************/ double Exp_b(double m) { return -m * Math.log(rn.nextDouble()); } /**************/ /* 全体の制御 */ /**************/ void Control() { // 到着時間の初期設定 for (int i1 = 0; i1 < inl.size(); i1++) { if (inl.get(i1).a_t == 0) inl.get(i1).arrive_time = Exp_b(inl.get(i1).mean); } // 実行制御 int sw[] = new int [2]; sw[0] = 0; while (sw[0] > -2) { Next(sw); // 次の処理の選択 if (sw[0] == -1) sw[0] = End_o_s(); // シミュレーションの終了 else { if (sw[0] == 0) Arrive(sw[1]); // 客の到着処理 else Service(sw[1]); // サービスの終了 } } } /*********************************************/ /* 次の処理の決定 */ /* sw[0] : =-1 : シミュレーションの終了 */ /* =0 : 客の到着処理 */ /* =1 : 窓口のサービス終了 */ /* [1] : 入り口番号 or 窓口番号 */ /*********************************************/ void Next(int sw[]) { double tm = end; // 次の処理時刻 sw[0] = -1; // 次の客の到着時刻 for (int i1 = 0; i1 < inl.size(); i1++) { Inlet x = inl.get(i1); if (x.arrive_time >= 0.0 && x.arrive_time < tm) { sw[0] = 0; sw[1] = i1; tm = x.arrive_time; } } // サービス終了時刻 for (int i1 = 0; i1 < ent.size(); i1++) { Entity x = ent.get(i1); if (x.service > 0 && x.end_time <= tm) { sw[0] = 1; sw[1] = i1; tm = x.end_time; } } if (sw[0] < 0) end = p_time; } /**********************************/ /* 終了処理 */ /* return : =-1 : 終了前処理 */ /* =-2 : 実際の終了 */ /**********************************/ int End_o_s() { int sw = -2; p_time = end; // 現在時刻 for (int i1 = 0; i1 < ent.size(); i1++) { Entity x = ent.get(i1); if (x.service > 0) { // サービス中の客はいるか? if (sw == -2) { sw = -1; end = x.end_time; // 窓口i1のサービス終了時刻 } else { if (x.end_time > end) end = x.end_time; // 窓口i1のサービス終了時刻 } } } return sw; } /************************/ /* 客の到着処理 */ /* kk : 入り口番号 */ /************************/ void Arrive(int kk) { /* 客数の増加と次の客の到着時刻の設定 */ nc += 1; // 到着客数カウンタ p_time = inl.get(kk).arrive_time; // 現在時刻 if (inl.get(kk).a_t == 0) // 次の客の到着時刻 inl.get(kk).arrive_time = p_time + Exp_b(inl.get(kk).mean); else if (inl.get(kk).a_t == 1) inl.get(kk).arrive_time = p_time + inl.get(kk).mean; else { if (inl.get(kk).que.isEmpty()) inl.get(kk).arrive_time = -1.0; else inl.get(kk).arrive_time = inl.get(kk).que.pollFirst().doubleValue(); } if (inl.get(kk).arrive_time >= end) inl.get(kk).arrive_time = -1.0; /* 系内客数の処理 */ c_now_c += cus.size() * (p_time - now_c_t); // 系内客数にその数が継続した時間を乗じた値の累計 now_c_t = p_time; // 現在の系内客数になった時刻 if ((int)cus.size()+1 > max_c) max_c = cus.size() + 1; // 最大系内客数 /* 空いている窓口を探す */ int k1 = inl.get(kk).out_n; que.get(k1).nc++; int k = -1; for (int i1 = 0; i1 < que.get(k1).m; i1++) { int k2 = que.get(k1).out_n.get(i1); // 処理窓口 if (ent.get(k2).service == 0) { k = k2; break; } } /* 窓口に空きがない場合 */ if (k < 0) { Customer ct_p = new Customer(0, k1, p_time); cus.put(new Integer(nc), ct_p); // 客の登録(系内客数) que.get(k1).c_ql += que.get(k1).que.size() * (p_time - que.get(k1).ql_t); // 待ち行列長にその長さが継続した時間を乗じた値の累計 que.get(k1).que.add(new Integer(nc)); // 客の登録(待ち行列) que.get(k1).ql_t = p_time; // 現在の待ち行列長になった時刻 if (que.get(k1).que.size() > que.get(k1).max_q_l) que.get(k1).max_q_l = que.get(k1).que.size(); // 最大待ち行列長 } /* すぐサービスをうけられる場合 */ else { Customer ct_p = new Customer(1, k, p_time); cus.put(new Integer(nc), ct_p); // 客の登録(系内客数) ent.get(k).service = nc; // サービスを受けている客番号 ent.get(k).busy_t = p_time; // 窓口がふさがった時刻 if (ent.get(k).s_t == 0) // 窓口のサービス終了時刻 ent.get(k).end_time = p_time + Exp_b(ent.get(k).mean); else ent.get(k).end_time = p_time + ent.get(k).mean; } } /**********************************/ /* サービス終了時の処理 */ /* kk : サービス終了窓口番号 */ /**********************************/ void Service(int kk) { /* 時間の設定 */ p_time = ent.get(kk).end_time; // 現在時刻 ent.get(kk).end_time = -1.0; // サービス終了時間 /* システムの外へ出る場合 */ if (ent.get(kk).to == 0) { /* 系内客数の処理 */ c_now_c += cus.size() * (p_time - now_c_t); // 系内客数にその数が継続した時間を乗じた値の累計 now_c_t = p_time; // 現在の系内客数になった時刻 /* 滞在時間の処理 */ Customer it = cus.get(new Integer(ent.get(kk).service)); // サービス中の客 double x1 = p_time - it.time; c_sys += x1; // 滞在時間の累計 if (x1 > max_sys) max_sys = x1; // 最大滞在時間 cus.remove(new Integer(ent.get(kk).service)); // 客の削除(系内客数) } /* 他の窓口処理へ入る場合の処理 */ else { int k1 = ent.get(kk).out_n; que.get(k1).nc++; int sw = 1; int k2 = 0; if (que.get(k1).que.size() == 0) { for (int i1 = 0; i1 < que.get(k1).m; i1++) { k2 = que.get(k1).out_n.get(i1); // 窓口 if (ent.get(k2).service == 0) { sw = 0; break; } } } /* 待ち行列がある場合 */ if (sw > 0) { que.get(k1).c_ql += que.get(k1).que.size() * (p_time - que.get(k1).ql_t); // 待ち行列長にその長さが継続した時間を乗じた値の累計 que.get(k1).que.add(new Integer(ent.get(kk).service)); // 客の登録(待ち行列) que.get(k1).ql_t = p_time; // 現在の待ち行列長になった時刻 if (que.get(k1).que.size() > que.get(k1).max_q_l) que.get(k1).max_q_l = que.get(k1).que.size(); // 最大待ち行列長 Customer it = cus.get(new Integer(ent.get(kk).service)); it.state1 = 0; // 客の状態変更(待ち行列) it.state2 = ent.get(kk).out_n; // 客の状態変更(待ち行列番号) } /* すぐサービスをうけられる場合 */ else { ent.get(k2).service = ent.get(kk).service; // サービスを受けている客番号 ent.get(k2).busy_t = p_time; // 窓口がふさがった時刻 if (ent.get(k2).s_t == 0) // 窓口のサービス終了時刻 ent.get(k2).end_time = p_time + Exp_b(ent.get(k2).mean); else ent.get(k2).end_time = p_time + ent.get(k2).mean; } } /* 窓口使用時間の処理 */ ent.get(kk).service = 0; // 窓口を空き状態にする ent.get(kk).c_busy += (p_time - ent.get(kk).busy_t); // 窓口がふさがっている時間の累計 /* この窓口に対する待ち行列がある場合 */ int k3 = ent.get(kk).in_n; if (que.get(k3).que.size() > 0) { que.get(k3).c_ql += que.get(k3).que.size() * (p_time - que.get(k3).ql_t); // 待ち行列長にその長さが継続した時間を乗じた値の累計 int n = que.get(k3).que.pollFirst().intValue(); // 待ち行列の先頭にいる客の削除 que.get(k3).ql_t = p_time; // 現在の待ち行列長になった時刻 Customer it = cus.get(new Integer(n)); double x1 = p_time - it.time; que.get(k3).c_wt += x1; // 待ち時間の累計 if (x1 > que.get(k3).max_wt) que.get(k3).max_wt = x1; // 最大待ち時間 for (int i1 = 0; i1 < que.get(k3).m; i1++) { int k4 = que.get(k3).out_n.get(i1); // 窓口 if (ent.get(k4).service == 0) { ent.get(k4).service = n; // 窓口の客番号 ent.get(k4).busy_t = p_time; // 窓口がふさがった時刻 if (ent.get(k4).s_t == 0) // 窓口のサービス終了時刻 ent.get(k4).end_time = p_time + Exp_b(ent.get(k4).mean); else ent.get(k4).end_time = p_time + ent.get(k4).mean; it.state1 = 1; // 客の状態変更(サービス中) it.state2 = k4; // 客の状態変更(窓口番号) break; } } } } /**************************/ /* 統計量の計算と最終出力 */ /**************************/ void Output() { // System System.out.printf("全客数 %d", nc); System.out.printf(" 最大系内客数 %d 最大滞在時間 %.3f\n", max_c, max_sys); System.out.printf(" 平均系内客数 %.3f", c_now_c / p_time); System.out.printf(" 平均滞在時間 %.3f", c_sys / nc); System.out.printf(" 終了時間 %.3f\n", p_time); // Entity for (int i1 = 0; i1 < ent.size(); i1++) { Entity e = ent.get(i1); System.out.printf("Entity %s 稼働率 %.3f\n", e.name, e.c_busy / p_time); } // Queue for (int i1 = 0; i1 < que.size(); i1++) { Queue q = que.get(i1); System.out.printf("Queue %s 客数 %d", q.name, q.nc); System.out.printf(" 最大待ち行列長 %d", q.max_q_l); System.out.printf(" 最大待ち時間 %.3f\n", q.max_wt); System.out.printf(" 平均待ち行列長 %.3f", q.c_ql / p_time); System.out.printf(" 平均待ち時間 %.3f\n", q.c_wt / q.nc); } } } /* ------------入力例(簡単な場合)----------- 1 Inlet 0 5 Queue 1 Queue 0 Inlet 2 Entity1 Entity2 2 Entity1 0 4 Queue 0 Entity2 0 4 Queue 0 10000 ------------入力例(複雑な場合)----------- 2 Inlet1 0 5 Queue1 Inlet2 0 5 Queue2 3 Queue1 0 Inlet1 1 Entity1 Queue2 0 Inlet2 1 Entity2 Queue3 2 Entity1 Entity2 2 Entity3 Entity4 4 Entity1 0 4 Queue1 1 Queue3 Entity2 0 4 Queue2 1 Queue3 Entity3 0 3 Queue3 0 Entity4 0 3 Queue3 0 10000 */