คิวจัดการข้อมูลในลักษณะเข้าก่อนออกก่อน หากคุณพยายามเพิ่มองค์ประกอบในคิวการบล็อกแบบเต็ม หรือลบองค์ประกอบออกจากคิวการบล็อกว่าง เธรดจะถูกบล็อก การบล็อกคิวเป็นเครื่องมือที่มีประโยชน์เมื่อหลายเธรดทำงานร่วมกัน เธรดผู้ปฏิบัติงานสามารถจัดเก็บผลลัพธ์ระดับกลางในคิวการบล็อกเป็นระยะ ๆ เธรดผู้ปฏิบัติงานอื่นๆ จะนำผลลัพธ์ระดับกลางออกมาและแก้ไขในอนาคต คิวจะปรับสมดุลโหลดโดยอัตโนมัติ หากเธรดชุดแรกทำงานช้ากว่าชุดที่สอง เธรดชุดที่สองจะบล็อกขณะรอผลลัพธ์ หากเธรดชุดแรกทำงานเร็ว ก็จะรอให้เธรดชุดที่สองตามทัน
โปรแกรมต่อไปนี้แสดงวิธีใช้คิวการบล็อกเพื่อควบคุมชุดของเธรด โปรแกรมค้นหาไฟล์ทั้งหมดในไดเร็กทอรีและไดเร็กทอรีย่อยทั้งหมด และพิมพ์รายการไฟล์ที่มีคำสำคัญที่ระบุ
แพ็คเกจ java.util.concurrent มี 4 รูปแบบของการบล็อกคิว: LinkedBlockingQueue, ArrayBlockingQueue, PriorityBlockingQueue และ DelayQueue เราใช้ ArrayBlockingQueue ArrayBlockingQueue ต้องใช้ความสามารถที่กำหนดเมื่อสร้าง และอาจต้องการความเป็นธรรมหรือไม่ก็ได้ หากตั้งค่าพารามิเตอร์ความเป็นธรรม เธรดที่มีเวลารอนานที่สุดจะถูกประมวลผลก่อน โดยทั่วไป ความเป็นธรรมจะทำให้คุณเสียประสิทธิภาพ ดังนั้นควรใช้เมื่อคุณต้องการมันจริงๆ เท่านั้น
เธรดผู้ผลิตแจกแจงไฟล์ทั้งหมดในไดเร็กทอรีย่อยทั้งหมดและวางลงในคิวการบล็อก การดำเนินการนี้รวดเร็ว และหากคิวไม่ได้ถูกจำกัดไว้ เร็วๆ นี้จะมีไฟล์ที่ไม่พบ
เรายังเริ่มชุดข้อความค้นหาจำนวนมากอีกด้วย แต่ละเธรดการค้นหาจะนำไฟล์จากคิว เปิดขึ้นมา พิมพ์บรรทัดทั้งหมดที่มีคำสำคัญ จากนั้นจึงนำไฟล์ถัดไป เราใช้เคล็ดลับเล็กๆ น้อยๆ เพื่อฆ่าเธรดหลังจากงานเสร็จสิ้น เมื่อต้องการส่งสัญญาณให้เสร็จสิ้น เธรดการแจงนับจะทำให้วัตถุเสมือนอยู่ในคิว (ซึ่งคล้ายกับการวางกระเป๋าเสมือนบนสายพานลำเลียงกระเป๋าที่ระบุว่า "กระเป๋าสุดท้าย") เมื่อเธรดการค้นหาดึงข้อมูลวัตถุเสมือน มันจะนำกลับและสิ้นสุด
โปรดทราบว่าไม่จำเป็นต้องมีการซิงโครไนซ์เธรดอย่างชัดเจนที่นี่ ในโปรแกรมนี้ เราใช้โครงสร้างข้อมูลคิวเป็นกลไกการซิงโครไนซ์
คัดลอกรหัสรหัสดังต่อไปนี้:
นำเข้า java.io.*;
นำเข้า java.util.*;
นำเข้า java.util.concurrent.*;
BlockingQueueTest คลาสสาธารณะ
-
โมฆะสาธารณะคง main (String [] args)
-
สแกนเนอร์ใน = สแกนเนอร์ใหม่ (System.in);
System.out.print("ป้อนไดเร็กทอรีฐาน (เช่น /usr/local/jdk1.6.0/src): ");
ไดเร็กทอรีสตริง = in.nextLine();
System.out.print("ป้อนคำสำคัญ (เช่น ระเหย): ");
สตริงคำหลัก = in.nextLine();
สุดท้าย int FILE_QUEUE_SIZE = 10;
SEARCH_THREADS int สุดท้าย = 100;
BlockingQueue<ไฟล์> คิว = ArrayBlockingQueue ใหม่ <ไฟล์>(FILE_QUEUE_SIZE);
ตัวแจงนับ FileEnumerationTask = FileEnumerationTask ใหม่ (คิว, ไฟล์ใหม่ (ไดเร็กทอรี));
เธรดใหม่ (ตัวแจงนับ) เริ่มต้น ();
สำหรับ (int i = 1; i <= SEARCH_THREADS; i++)
เธรดใหม่ (SearchTask ใหม่ (คิว, คำสำคัญ)). เริ่มต้น ();
-
-
-
* งานนี้ระบุไฟล์ทั้งหมดในไดเร็กทอรีและไดเร็กทอรีย่อย
-
คลาส FileEnumerationTask ใช้งาน Runnable
-
-
* สร้าง FileEnumerationTask
* @param เข้าคิวคิวการบล็อกซึ่งมีการเพิ่มไฟล์ที่ระบุ
* @param beginningDirectory คือไดเร็กทอรีที่ใช้เริ่มการแจงนับ
-
FileEnumerationTask สาธารณะ (คิว BlockingQueue <ไฟล์> ไฟล์ beginningDirectory)
-
this.queue = คิว;
this.startingDirectory = beginningDirectory;
-
การรันโมฆะสาธารณะ ()
-
พยายาม
-
แจกแจง (เริ่มต้นไดเรกทอรี);
Queue.put(ดัมมี่);
-
จับ (InterruptedException e)
-
-
-
-
* ระบุไฟล์ทั้งหมดในไดเร็กทอรีที่กำหนดและไดเร็กทอรีย่อยซ้ำ ๆ
* @param directory คือไดเร็กทอรีที่จะเริ่มต้น
-
การระบุโมฆะสาธารณะ (ไดเร็กทอรีไฟล์) พ่น InterruptedException
-
ไฟล์ [] ไฟล์ = directory.listFiles ();
สำหรับ (ไฟล์ไฟล์ : files)
-
ถ้า (file.isDirectory()) ระบุ (ไฟล์);
อื่น Queue.put (ไฟล์);
-
-
ไฟล์คงที่สาธารณะ DUMMY = ไฟล์ใหม่ ("");
คิว BlockingQueue <ไฟล์> ส่วนตัว;
ไฟล์ส่วนตัว beginningDirectory;
-
-
* งานนี้ค้นหาไฟล์ด้วยคำสำคัญที่กำหนด
-
คลาส SearchTask ใช้งาน Runnable
-
-
* สร้าง SearchTask
* @param เข้าคิวคิวที่จะรับไฟล์
* @param คีย์เวิร์ดเป็นคีย์เวิร์ดที่ต้องการค้นหา
-
SearchTask สาธารณะ (คิว BlockingQueue <ไฟล์>, คีย์เวิร์ดสตริง)
-
this.queue = คิว;
this.keyword = คำหลัก;
-
การรันโมฆะสาธารณะ ()
-
พยายาม
-
บูลีนเสร็จแล้ว = เท็จ;
ในขณะที่ (!ทำ)
-
ไฟล์ไฟล์ = Queue.take();
ถ้า (ไฟล์ == FileEnumerationTask.DUMMY)
-
Queue.put(ไฟล์);
เสร็จแล้ว = จริง;
-
ค้นหาอย่างอื่น (ไฟล์);
-
-
จับ (IOException จ)
-
e.printStackTrace();
-
จับ (InterruptedException e)
-
-
-
-
* ค้นหาไฟล์ด้วยคำสำคัญที่กำหนดและพิมพ์บรรทัดที่ตรงกันทั้งหมด
* @param ไฟล์ไฟล์ที่ต้องการค้นหา
-
การค้นหาโมฆะสาธารณะ (ไฟล์ไฟล์) พ่น IOException
-
สแกนเนอร์ใน = สแกนเนอร์ใหม่ (FileInputStream ใหม่ (ไฟล์));
int lineNumber = 0;
ในขณะที่ (in.hasNextLine())
-
หมายเลขบรรทัด++;
เส้นสตริง = in.nextLine().trim();
if (line.contains(คำสำคัญ)) System.out.printf("%s:%d %s%n", file.getPath(), lineNumber, line);
-
ใน.ปิด();
-
คิว BlockingQueue <ไฟล์> ส่วนตัว;
คำหลักสตริงส่วนตัว;
-