تقوم قوائم الانتظار بإدارة البيانات بطريقة الوارد أولاً يخرج أولاً. إذا حاولت إضافة عنصر إلى قائمة انتظار حظر كاملة، أو إزالة عنصر من قائمة انتظار حظر فارغة، فسيتم حظر مؤشر الترابط. تعد قوائم الانتظار المحظورة أداة مفيدة عندما تتعاون عدة سلاسل رسائل. يمكن لمؤشر الترابط العامل تخزين النتائج المتوسطة بشكل دوري في قائمة انتظار الحظر. تقوم سلاسل العمليات الأخرى بإخراج النتائج المتوسطة وتعديلها في المستقبل. تقوم قائمة الانتظار تلقائيًا بموازنة الحمل. إذا كانت المجموعة الأولى من المواضيع تعمل بشكل أبطأ من المجموعة الثانية، فسيتم حظر المجموعة الثانية من المواضيع أثناء انتظار النتائج. إذا كانت المجموعة الأولى من سلاسل الرسائل تعمل بسرعة، فسوف تنتظر المجموعة الثانية من سلاسل الرسائل للحاق بها.
يوضح البرنامج التالي كيفية استخدام قوائم الانتظار المحظورة للتحكم في مجموعات من مؤشرات الترابط. يقوم البرنامج بالبحث في كافة الملفات الموجودة في الدليل وجميع الدلائل الفرعية الخاصة به ويطبع قائمة بالملفات التي تحتوي على الكلمة الأساسية المحددة.
توفر الحزمة java.util.concurrent 4 أنواع مختلفة من قوائم الانتظار المحظورة: LinkedBlockingQueue، وArrayBlockingQueue، وPriorityBlockingQueue، وDelayQueue. نحن نستخدم ArrayBlockingQueue. يتطلب ArrayBlockingQueue سعة معينة عند إنشائه، ويمكن أن يتطلب العدالة بشكل اختياري. إذا تم تعيين معلمة الإنصاف، فستتم معالجة سلسلة الرسائل ذات وقت الانتظار الأطول أولاً. بشكل عام، ستكلفك العدالة في الأداء، لذا استخدمها فقط عندما تحتاج إليها حقًا.
يقوم مؤشر ترابط المنتج بتعداد جميع الملفات في جميع الدلائل الفرعية ويضعها في قائمة انتظار الحظر. هذه العملية سريعة، وإذا لم يتم تحديد قائمة الانتظار، فسوف تحتوي قريبًا على ملفات لم يتم العثور عليها.
لقد بدأنا أيضًا عددًا كبيرًا من سلاسل البحث. يأخذ كل مؤشر ترابط بحث ملفًا من قائمة الانتظار، ويفتحه، ويطبع كافة الأسطر التي تحتوي على الكلمة الأساسية، ثم يأخذ الملف التالي. نستخدم خدعة صغيرة لقتل الخيط بعد الانتهاء من العمل. للإشارة إلى الاكتمال، يضع مؤشر ترابط التعداد كائنًا افتراضيًا في قائمة الانتظار. (يشبه هذا وضع حقيبة افتراضية على ناقل الأمتعة مكتوب عليها "Last Bag.") عندما يسترد مؤشر ترابط البحث الكائن الافتراضي، فإنه يعيده وينتهي.
لاحظ أنه لا يلزم وجود مزامنة صريحة لمؤشر الترابط هنا. في هذا البرنامج، نستخدم بنية بيانات قائمة الانتظار كآلية للمزامنة.
انسخ رمز الكود كما يلي:
استيراد java.io.*;
import java.util.*;
import java.util.concurrent.*;
اختبار BlockingQueueTest للطبقة العامة
{
الفراغ العام الثابت الرئيسي (String[] args)
{
الماسح الضوئي في = الماسح الضوئي الجديد (System.in)؛
System.out.print("أدخل الدليل الأساسي (على سبيل المثال /usr/local/jdk1.6.0/src):");
دليل السلسلة = in.nextLine();
System.out.print("أدخل الكلمة الرئيسية (على سبيل المثال المتقلبة):");
الكلمة الأساسية السلسلة = in.nextLine();
النهائي FILE_QUEUE_SIZE = 10؛
البحث النهائي SEARCH_THREADS = 100؛
BlockingQueue<File> queue = new ArrayBlockingQueue<File>(FILE_QUEUE_SIZE);
FileEnumerationTask enumerator = new FileEnumerationTask(queue, new File(directory));
موضوع جديد(التعداد).start();
لـ (int i = 1; i <= SEARCH_THREADS; i++)
موضوع جديد(new SearchTask(queue,keyword)).start();
}
}
/**
* تقوم هذه المهمة بتعداد جميع الملفات الموجودة في الدليل وأدلته الفرعية.
*/
تقوم فئة FileEnumerationTask بتنفيذ Runnable
{
/**
* إنشاء FileEnumerationTask.
*param queue قائمة انتظار الحظر التي تضاف إليها الملفات المذكورة
* @param beginDirectory الدليل الذي سيتم فيه بدء التعداد
*/
FileEnumerationTask العام (قائمة انتظار BlockingQueue<File>، دليل بدء الملف)
{
this.queue = queue;
this.startingDirectory = beginDirectory;
}
تشغيل الفراغ العام ()
{
يحاول
{
تعداد(startingDirectory);
queue.put(DUMMY);
}
قبض على (InterruptedException ه)
{
}
}
/**
* يقوم بشكل متكرر بتعداد جميع الملفات الموجودة في دليل معين وأدلته الفرعية
* @param الدليل الدليل الذي يجب البدء فيه
*/
تعداد الفراغ العام (دليل الملف) يطرح InterruptedException
{
File[] files = Directory.listFiles();
لـ (ملف الملف: الملفات)
{
إذا (file.isDirectory()) تعداد (ملف)؛
else queue.put(file);
}
}
ملف ثابت عام DUMMY = ملف جديد("");
قائمة انتظار BlockingQueue<File> الخاصة؛
دليل بدء الملف الخاص؛
}
/**
* تقوم هذه المهمة بالبحث في الملفات عن كلمة رئيسية معينة.
*/
تقوم فئة SearchTask بتنفيذ Runnable
{
/**
* يبني SearchTask.
* @param قائمة الانتظار التي سيتم أخذ الملفات منها
* @param الكلمة الأساسية هي الكلمة الأساسية التي يجب البحث عنها
*/
SearchTask العامة (قائمة انتظار BlockingQueue<File>، الكلمة الأساسية لسلسلة)
{
this.queue = queue;
this.keyword = الكلمة الأساسية؛
}
تشغيل الفراغ العام ()
{
يحاول
{
تم منطقيًا = خطأ؛
بينما (! تم)
{
ملف الملف = queue.take();
إذا (ملف == FileEnumerationTask.DUMMY)
{
queue.put(file);
تم = صحيح؛
}
بحث آخر (ملف)؛
}
}
قبض (IOException ه)
{
printStackTrace();
}
قبض على (InterruptedException ه)
{
}
}
/**
* يبحث في ملف عن كلمة رئيسية معينة ويطبع جميع الأسطر المطابقة.
*param ملف الملف للبحث
*/
البحث عن الفراغ العام (ملف ملف) يلقي IOException
{
Scanner in = new Scanner(new FileInputStream(file));
عدد السطر int = 0؛
بينما (in.hasNextLine())
{
lineNumber++;
خط السلسلة = in.nextLine().trim();
if (line.contains(keyword)) System.out.printf("%s:%d %s%n", file.getPath(), lineNumber, line);
}
in. Close();
}
قائمة انتظار BlockingQueue<File> الخاصة؛
الكلمة الأساسية سلسلة خاصة؛
}