แนะนำ:
เมื่อไม่นานมานี้ฉันไปที่ธนาคารเพื่อจัดการธุรกิจและมีคนมากมายอยู่ในสาย ใช้เวลาน้อยกว่า 5 นาทีในการจัดการธุรกิจด้วยตัวเอง แต่ฉันรอสองชั่วโมง (ฉันเชื่อว่าหลายคนพบสถานการณ์นี้) ฉันพูดไม่ออกเกี่ยวกับระดับการบริการนี้ แต่ปัญหาเกิดขึ้นอีกครั้ง ธนาคารควรเปิดหน้าต่างหลายบานเพื่อให้แน่ใจว่าคุณภาพการบริการโดยรวมและอัตราการใช้ทรัพยากรการใช้งาน? ต่อไปเราจะจำลองปัญหานี้ผ่านทฤษฎีคิว
รู้เบื้องต้นเกี่ยวกับทฤษฎีคิว
ทฤษฎีการรอคิวเป็นทฤษฎีทางคณิตศาสตร์และวิธีการที่ศึกษาปรากฏการณ์ของการรวบรวมแบบสุ่มและการกระจายตัวของระบบและวิศวกรรมการทำงานของระบบสุ่ม เป็นที่รู้จักกันในนามทฤษฎีของระบบบริการแบบสุ่มและเป็นสาขาหนึ่งของการวิจัยการดำเนินงาน มาทำให้ทฤษฎีการเข้าคิวง่ายขึ้นด้านล่างและดูรูปต่อไปนี้ก่อน:
เราจัดโต๊ะบริการสีน้ำเงินหลายแห่งที่ด้านซ้ายของรูปภาพกับลูกค้าสีแดงที่อาจมาทางขวาและพื้นที่รอสีเหลืองอยู่ตรงกลาง หากแผนกบริการไม่ได้ใช้งานลูกค้าสามารถรับบริการโดยตรงไม่เช่นนั้นพวกเขาจะต้องรอในพื้นที่สีเหลือง คำสั่งของการบริการลูกค้าใช้หลักการของบริการมาก่อนและบริการปัจจุบัน ตอนนี้ถ้าเรารู้ว่าการกระจายความน่าจะเป็นของลูกค้าที่กำลังจะมาเราจะจัดให้มีแผนกบริการหลายแห่งทางด้านซ้ายเพื่อให้ได้ระดับการบริการที่ดีขึ้นและให้แน่ใจว่าอัตราการใช้งานของโต๊ะบริการ ต่อไปเราจะสร้างแบบจำลองเพื่อจำลองปัญหานี้
ทฤษฎีการเข้าคิวถูกนำไปใช้ทีละขั้นตอน
1) สำหรับทฤษฎีการเข้าคิวเราต้องกำหนดคุณลักษณะของลูกค้าก่อนที่จะรู้ว่าเมื่อไหร่ที่ลูกค้ามาถึงเวลาการบริการที่จำเป็น ฯลฯ ก่อนอื่นเราจะสร้างคลาสลูกค้าที่เราระบุเวลาสูงสุดและขั้นต่ำสำหรับการบริการลูกค้า ที่นี่เพื่อให้ง่ายขึ้นเราคิดโดยตรงว่าเวลาให้บริการสุ่มอย่างสมบูรณ์:
Public Class CustomerBean {// เวลาการให้บริการขั้นต่ำส่วนตัวคงที่ int minservetime = 3 * 1000; // เวลาการให้บริการสูงสุดส่วนตัว int maxServetime = 15 * 1000; // ลูกค้าถึงเวลาที่มาของส่วนตัวเป็นเวลานาน; // ลูกค้าต้องการเวลาบริการส่วนตัว int servetime; Public CustomerBean () {// ตั้งค่าเวลามาถึงการมาถึง = System.currentTimeMillis (); // สุ่มตั้งค่าเวลาการบริการลูกค้า servetime = (int) (math.random () * (maxServetime - minServetime) + minServetime); - 2) เรากำหนดลูกค้าข้างต้นแล้วเราจำเป็นต้องกำหนดคิวคิว ก่อนอื่นให้ดูที่คุณลักษณะของคิว ที่นี่เรากำหนดอาร์เรย์เพื่อประหยัดลูกค้าที่เข้าคิวกำหนดช่วงเวลาขั้นต่ำและสูงสุดสำหรับลูกค้ารายต่อไปที่จะมาถึงและความน่าจะเป็นของลูกค้าที่จะมา (เพื่ออธิบายสั้น ๆ ที่นี่หากช่วงเวลาของลูกค้ารายต่อไปคือ 3
Public Class CustomerQuene {// กำลังรอคิวลูกค้า LinkedList ส่วนตัว <CeversenterBean> ลูกค้า = ใหม่ LinkedList <CustomerBean> (); // เวลาที่สั้นที่สุดสำหรับลูกค้ารายต่อไปที่จะมาเป็นส่วนตัว int mintime = 0; // เวลาสูงสุดสำหรับลูกค้ารายต่อไปที่จะมาเป็นส่วนตัว int maxtime = 1 * 1000; // ความน่าจะเป็นที่ลูกค้าจะมาถึงอัตราคู่ส่วนตัว = 0.9; // ระบุว่าธงบูลีนส่วนตัวของลูกค้า = true; // จำนวนสูงสุดของคนที่เข้าคิว INT ส่วนตัว maxwaitnum = 0; - 3) เมื่อมีลูกค้าและคิวเราตั้งเธรดเพื่อสร้างลูกค้าเพื่อสร้างลูกค้าอย่างต่อเนื่อง นี่คือเวลาและการแจกแจงความน่าจะเป็นที่เรากล่าวถึงข้างต้น
/ ***@คำอธิบาย: สร้างเธรดลูกค้า*@เวอร์ชัน: 1.1.0*/ คลาสส่วนตัว customerThread ขยายเธรด {Private CustomerThread (ชื่อสตริง) {super (ชื่อ); } @Override โมฆะสาธารณะ Run () {ในขณะที่ (FLAG) {// เพิ่มลูกค้าใหม่ในตอนท้ายของทีมถ้า (math.random () <อัตรา) {customer.addlast (ลูกค้าใหม่ ()); if (maxwaitnum <customer.size ()) {maxwaitnum = customer.size (); }} int sleeptime = (int) (math.random () * (maxtime - mintime) + mintime); ลอง {timeunit.milliseconds.sleep (เวลานอน); } catch (exception e) {e.printstacktrace (); - 4) หากมีลูกค้าในคิวคิวเพื่อตัดในแผนกบริการฟรีคุณต้องให้ลูกค้าในหัวหน้าทีมเพื่อรับบริการ
Public Synchronized CustomerBean GetCustomerBean () {ถ้า (ลูกค้า == NULL || cheaments.size () <1) {return null; } ส่งคืนลูกค้า removefirst (); - 5) คุณลักษณะและวิธีการที่เกี่ยวข้องกับลูกค้าพร้อมแล้ว มาตั้งค่าแอตทริบิวต์ที่เกี่ยวข้องกับโต๊ะบริการ ที่นี่เราตั้งค่าแผนกบริการโดยตรงเป็นเธรดเพื่อกำหนดตัวบ่งชี้บริการบางอย่างเช่นจำนวนลูกค้าที่ให้บริการเวลารอคอยทั้งหมดเวลาบริการทั้งหมดเวลารอคอยสูงสุด ฯลฯ
ชั้นเรียนสาธารณะ ServantThread ขยายเธรด {// จำนวนลูกค้าบริการส่วนตัวคงที่ int customernum = 0; // เวลารอรวมเวลาส่วนตัวคงที่ int sumwaittime = 0; // เวลาการให้บริการทั้งหมดแบบคงที่ int sumservetime = 0; // เวลารอสูงสุดส่วนตัว int int maxwaittime = 0; ธงบูลีนส่วนตัว = เท็จ; ชื่อสตริงส่วนตัว; - 6) งานหลักของแผนกบริการคือการให้บริการลูกค้า ที่นี่เราเขียนการดำเนินงานที่เกี่ยวข้องกับการให้บริการลูกค้าในวิธีการเรียกใช้ของเธรด
โมฆะสาธารณะเรียกใช้ () {flag = true; ในขณะที่ (FLAG) {customerBean customer = customerquene.getCustomerquene (). getCustomerBean (); // หากเธรดลูกค้าถูกปิดและไม่มีลูกค้าในคิวเธรดแผนกบริการจะปิดและเผยแพร่หาก (ลูกค้า == null) {ถ้า (! customerquene.getCustomerquene (). isflag ()) {flag = false; พิมพ์(); } ดำเนินการต่อ; } Long Now = System.currentTimeMillis (); int waittime = (int) (ตอนนี้ - customer.getArrivetime ()); // บันทึกเวลารอสูงสุดถ้า (waittime> maxwaittime) {maxWaittime = waittime; } // เวลานอนเป็นเวลาบริการของลูกค้าซึ่งแสดงถึงระยะเวลาการให้บริการในช่วงเวลานี้ให้บริการลูกค้า ลอง {timeunit.milliseconds.sleep (customer.getServetime ()); } catch (exception e) {e.printstacktrace (); } system.err.println (ชื่อ + "เวลาในการให้บริการลูกค้า:" + customer.getServeservetime () + "ลูกค้า MS/T รอ:" + waittime + "MS"); Customernum ++; sumwaittime += waittime; SUMSERVETIME += customer.getServetime (); - 7) ในที่สุดเราเขียนแบบทดสอบเพื่อตรวจสอบระดับบริการ
/ ** *@คำอธิบาย: */ แพ็คเกจ com.lulei.opsearch.quene; นำเข้า java.util.concurrent.timeUnit; การทดสอบระดับสาธารณะ {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {// เปิด system.out.out.println ("เปิดประตูและรับลูกค้า!"); ธงบูลีน = จริง; customerquene.getCustomerquene (); ยาว a = system.currenttimeMillis (); int servicenum = 10; สำหรับ (int i = 0; i <serviceNum; i ++) {servantThread thread = new ServantThread ("Service Desk"+i); thread.start (); } ในขณะที่ (ธง) {long b = system.currentTimeMillis (); if (b - a> 1 * 60 * 1000 && flag) {// close flag = false; customerquene.getCustomerquene (). Close (); System.out.println ("ปิดประตูและอย่ารับลูกค้า!"); } system.out.println ("เวลาทำงานของระบบ:" + (b -a) + "ms"); System.out.println ("เวลาว่างของระบบ:" + ((b -a) * servantnum - servantthread.getsumservetime ())); ServantThread.print (); ลอง {timeunit.seconds.sleep (2); } catch (exception e) {e.printstacktrace (); - การรันผลลัพธ์
1) จุดเริ่มต้นของการดำเนินการ
2) ลูกค้าสร้างการปิดเธรด
3) ระดับบริการสุดท้าย
โดยการแก้ไขจำนวนโต๊ะบริการคุณสามารถประเมินจำนวนโต๊ะบริการควรตั้งค่าในสถานการณ์ลูกค้าปัจจุบัน
กรอกรหัส
1) หมวดหมู่ลูกค้า
/ ** *@คำอธิบาย: */ แพ็คเกจ com.lulei.opsearch.quene; Public Class CustomerBean {// เวลาการให้บริการขั้นต่ำส่วนตัวคงที่ int minservetime = 3 * 1000; // เวลาการให้บริการสูงสุดส่วนตัว int maxServetime = 15 * 1000; // ลูกค้าถึงเวลาที่มาของส่วนตัวเป็นเวลานาน; // ลูกค้าต้องการเวลาบริการส่วนตัว int servetime; Public CustomerBean () {// ตั้งค่าเวลามาถึงการมาถึง = System.currentTimeMillis (); // ตั้งค่าเวลาการบริการลูกค้าแบบสุ่ม servetime = (int) (math.random () * (MaxServetime - MinServetime) + MinServetime); } สาธารณะคงที่ int getMinServetime () {return minservetime; } โมฆะคงที่สาธารณะ setMinServetime (int minServetime) {customerBean.minservetime = minServetime; } สาธารณะคงที่ int getMaxServetime () {return maxServetime; } โมฆะคงที่สาธารณะ setMaxServetime (int maxServetime) {customerBean.maxServetime = maxServetime; } public long getArrivetime () {return archetime; } โมฆะสาธารณะ setarrivetime (การมาถึงยาว) {this.arrivetime = arrivetime; } public int getServetime () {return servetime; } โมฆะสาธารณะ setServetime (int servetime) {this.servetime = servetime; -2) คิวลูกค้า
/ ** *@คำอธิบาย: */ แพ็คเกจ com.lulei.opsearch.quene; นำเข้า java.util.linkedList; นำเข้า java.util.concurrent.timeUnit; Public Class CustomerQuene {// กำลังรอคิวลูกค้า LinkedList ส่วนตัว <CeversenterBean> ลูกค้า = ใหม่ LinkedList <CustomerBean> (); // เวลาที่สั้นที่สุดสำหรับลูกค้ารายต่อไปที่จะมาเป็นส่วนตัว int mintime = 0; // เวลาสูงสุดสำหรับลูกค้ารายต่อไปที่จะมาเป็นส่วนตัว int maxtime = 1 * 1000; // ความน่าจะเป็นของลูกค้าที่มาถึงสองอัตราส่วนตัว = 0.9; // ระบุว่าลูกค้ายังคงสร้างธงบูลีนส่วนตัว = true; // จำนวนสูงสุดของคนที่เข้าคิว INT ส่วนตัว maxwaitnum = 0; สาธารณะ int getMaxWaitNum () {return maxwaitnum; } บูลีนสาธารณะ isflag () {return flag; } / ** * @return * @author: lulei * @description: รับลูกค้าในหัวของคิว * / สาธารณะที่ซิงโครไนซ์ลูกค้า getCustomerBean () {ถ้า (ลูกค้า == null || ลูกค้า } ส่งคืนลูกค้า removefirst (); } public void close () {if (flag) {flag = false; }} / ** * @return * @author: lulei * @description: รับจำนวนลูกค้ารอ * / สาธารณะ int getwaitcustomernum () {return customer.size (); } / ***@คำอธิบาย: สร้างเธรดลูกค้า*@เวอร์ชัน: 1.1.0* / คลาสส่วนตัว CustomerThread ขยายเธรด {Private CustomerThread (ชื่อสตริง) {super (ชื่อ); } @Override โมฆะสาธารณะ Run () {ในขณะที่ (FLAG) {// เพิ่มลูกค้าใหม่ในตอนท้ายของทีมถ้า (math.random () <อัตรา) {customer.addlast (ลูกค้าใหม่ ()); if (maxwaitnum <customer.size ()) {maxwaitnum = customer.size (); }} int sleeptime = (int) (math.random () * (maxtime - mintime) + mintime); ลอง {timeunit.milliseconds.sleep (เวลานอน); } catch (exception e) {e.printstacktrace (); }}}}} // โหมด Singleton เริ่มต้นคลาสสแตติกคลาสส่วนตัว customerQuenedao {ลูกค้าคงที่ customerquene customerquene = new CustomerQuene (); } Private CustomerQuene () {comveryThread customerThread = new CustomerThread ("เธรดการสร้างลูกค้า"); customerThread.start (); } public customerquene getCustomerquene () {ส่งคืน customerQuenedao.customerquene; } // โหมดโหมดซิงเกิลสิ้นสุด int public int getMintime () {return mintime; } โมฆะสาธารณะ setMintime (int mintime) {this.mintime = mintime; } public int getMaxtime () {return maxtime; } โมฆะสาธารณะ setMaxtime (int maxtime) {this.maxtime = maxtime; } สาธารณะ double getrate () {อัตราผลตอบแทน; } โมฆะสาธารณะ setrate (อัตราสองเท่า) {this.rate = อัตรา; - 3) เธรดแผนกบริการ
/ ** *@คำอธิบาย: */ แพ็คเกจ com.lulei.opsearch.quene; นำเข้า java.util.concurrent.timeUnit; นำเข้า com.lulei.util.parseutil; ชั้นเรียนสาธารณะ ServantThread ขยายเธรด {// จำนวนลูกค้าบริการส่วนตัวคงที่ int customernum = 0; // เวลารอรวมเวลาส่วนตัวคงที่ int sumwaittime = 0; // เวลาการให้บริการทั้งหมดแบบคงที่ int sumservetime = 0; // เวลารอสูงสุดส่วนตัว int int maxwaittime = 0; ธงบูลีนส่วนตัว = เท็จ; ชื่อสตริงส่วนตัว; Public ServantThread (ชื่อสตริง) {super (ชื่อ); this.name = ชื่อ; } สาธารณะคงที่ int getMaxWaittime () {return maxwaittime; } สาธารณะ int คงที่ getumservetime () {return sumservetime; } @Override โมฆะสาธารณะ Run () {flag = true; ในขณะที่ (FLAG) {customerBean customer = customerquene.getCustomerquene (). getCustomerBean (); // หากเธรดลูกค้าถูกปิดและไม่มีลูกค้าในคิวเธรดแผนกบริการจะปิดและเผยแพร่หาก (ลูกค้า == null) {ถ้า (! customerquene.getCustomerquene (). isflag ()) {flag = false; พิมพ์(); } ดำเนินการต่อ; } Long Now = System.currentTimeMillis (); int waittime = (int) (ตอนนี้ - customer.getArrivetime ()); // บันทึกเวลารอสูงสุดถ้า (waittime> maxwaittime) {maxWaittime = waittime; } // เวลานอนเป็นเวลาบริการของลูกค้าซึ่งแสดงถึงการลองของลูกค้า {timeunit.milliseconds.sleep (customer.getServetime ()); } catch (exception e) {e.printstacktrace (); } system.err.println (ชื่อ + "เวลาในการให้บริการลูกค้า:" + customer.getServetime () + "MS/T การรอลูกค้า:" + waittime + "MS"); Customernum ++; sumwaittime += waittime; SUMSERVETIME += customer.getServetime (); }} public static void print () {if (customernum> 0) { System.out.println ("------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - // ส่งออกเวลารอคอยโดยเฉลี่ยของลูกค้าและรักษาสองตำแหน่งทศนิยม system.out.println ("เวลารอคอยเฉลี่ยสำหรับลูกค้า:" + parseutil.parsedoubleTodouble (sumwaittime * 1.0 /customernum), 2) + "MS"); / customernum), 2) + "MS"); 4) ทดสอบโมเดล
/ ** *@คำอธิบาย: */ แพ็คเกจ com.lulei.opsearch.quene; นำเข้า java.util.concurrent.timeUnit; การทดสอบระดับสาธารณะ {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {// เปิด system.out.out.println ("เปิดประตูและรับลูกค้า!"); ธงบูลีน = จริง; customerquene.getCustomerquene (); ยาว a = system.currenttimeMillis (); int servicenum = 10; สำหรับ (int i = 0; i <serviceNum; i ++) {servantThread thread = new ServantThread ("Service Desk"+i); thread.start (); } ในขณะที่ (ธง) {long b = system.currentTimeMillis (); if (b - a> 1 * 60 * 1000 && flag) {// close flag = false; customerquene.getCustomerquene (). Close (); System.out.println ("ปิดประตูและอย่ารับลูกค้า!"); } system.out.println ("เวลาทำงานของระบบ:" + (b -a) + "ms"); System.out.println ("เวลาว่างของระบบ:" + ((b -a) * servantnum - servantthread.getsumservetime ())); ServantThread.print (); ลอง {timeunit.seconds.sleep (2); } catch (exception e) {e.printstacktrace (); -ข้างต้นเป็นการแนะนำรายละเอียดเกี่ยวกับหลักการของทฤษฎีการจัดคิว Java ฉันหวังว่ามันจะเป็นประโยชน์กับการเรียนรู้ของทุกคน