يعد تجميع سلاسل الرسائل ميزة مثيرة للاهتمام توفرها واجهة برمجة تطبيقات Java المتزامنة. يمكننا التعامل مع مجموعة من الخيوط كوحدة مستقلة ويمكننا التعامل مع كائنات الخيوط في مجموعة الخيوط حسب الرغبة. على سبيل المثال، يمكنك التحكم في مجموعة من سلاسل العمليات لتشغيل نفس المهمة دون الاهتمام بعدد سلاسل الرسائل التي لا تزال قيد التشغيل، ويمكنك أيضًا استخدام استدعاء المقاطعة لمقاطعة تنفيذ جميع سلاسل الرسائل.
توفر Java فئة ThreadGroup للتحكم في مجموعة مؤشرات الترابط. يمكن إنشاء مجموعة مؤشرات ترابط من خلال كائن مؤشر ترابط، أو يمكن إنشاؤها بواسطة مجموعات مؤشرات ترابط أخرى لإنشاء بنية شجرة لمؤشرات الترابط.
وفقًا لـ "Effective Java"، لم يعد استخدام ThreadGroup موصى به. يوصى باستخدام Executor.
—— يشرح D Guagot هذا.
في هذا القسم، نستخدم ThreadGroup لتطوير مثال بسيط. سنقوم بإنشاء عشرة سلاسل بأوقات نوم مختلفة (مثل محاكاة البحث) وعندما يكتمل أحدها، نقوم بمقاطعة الباقي.
تعرف عليه
اتبع الخطوات الموضحة أدناه لإكمال نموذج التعليمات البرمجية.
1. قم بإنشاء فئة باسم النتيجة لتخزين اسم الموضوع الأول لإكمال المهمة. قم بتعريف متغير خاص من النوع String، واسمه، وقم بإنشاء أساليب Setter/Getter. الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
نتيجة الطبقة العامة {
اسم سلسلة خاصة؛
سلسلة عامة getName () {
اسم الإرجاع؛
}
اسم مجموعة الفراغ العام (اسم السلسلة) {
this.name = name;
}
}
2. قم بإنشاء فئة باسم SearchTask وقم بتنفيذ الواجهة القابلة للتشغيل. الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
فئة عامة SearchTask تنفذ Runnable {
3. قم بتعريف متغير خاص من النوع النتيجة وإنشاء مثيل للمتغير من خلال المُنشئ. الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
نتيجة النتيجة الخاصة؛
مهمة البحث العامة (نتيجة النتيجة) {
this.result = result;
}
4. قم بتنفيذ طريقة التشغيل () واستدعاء طريقة doTask () فيها لانتظار الاكتمال أو الانقطاع. تقوم هذه الطريقة أيضًا بطباعة المعلومات إلى وحدة التحكم لإظهار بداية مؤشر الترابط أو نهايته أو انقطاعه. الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
@تجاوز
تشغيل الفراغ العام () {
اسم السلسلة = Thread.currentThread().getName();
System.out.printf("الموضوع %s: البدء/n"، الاسم)؛
يحاول {
doTask();
result.setName(name);
} قبض على (InterruptedException e) {
System.out.printf("مؤشر الترابط %s: تمت مقاطعته/n"، name);
يعود؛
}
System.out.printf("الموضوع %s: النهاية/n"، الاسم)؛
}
5. قم بتنفيذ طريقة doTask ()، والتي ستنشئ كائنًا عشوائيًا ثم تستخدم الكائن لإنشاء رقم عشوائي لضبط وقت سكون مؤشر الترابط. الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
// محاكاة البحث
doTask () الخاص باطلة يلقي InterruptedException {
عشوائي عشوائي = عشوائي جديد (تاريخ جديد ().getTime ())؛
int value = (int) (random.nextDouble() * 100);
System.out.printf("مؤشر الترابط %s: %d/n"،
Thread.currentThread().getName(), value);
TimeUnit.SECONDS.sleep(value);
}
6. قم بإنشاء الفئة الرئيسية لنموذج البرنامج، Main، وقم بتنفيذ الطريقة main(). الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
الطبقة العامة الرئيسية {
public static void main(String[] args) {
7. قم بإنشاء كائن ThreadGroup باسم الباحث. الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
ThreadGroup threadGroup = new ThreadGroup("Searcher");
8. ثم قم بإنشاء كائن النتيجة وكائن SearchTask. الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
نتيجة النتيجة = نتيجة جديدة ()؛
SearchTask searchTask = new SearchTask(result);
9. استخدم كائن SearchTask لإنشاء عشرة كائنات Thread، وعند إنشاء كائن Thread، قم بتمرير كائن ThreadGroup كمعلمة أولى إلى مُنشئ فئة Thread. الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
لـ (int i = 0; i < 5; i++) {
Thread thread = new Thread(threadGroup, searchTask);
Thread.start();
يحاول {
TimeUnit.SECONDS.sleep(1);
} قبض على (InterruptedException e) {
printStackTrace();
}
}
10. استخدم طريقة القائمة () لطباعة معلومات كائن ThreadGroup. الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
System.out.printf("عدد المواضيع: %d/n"، threadGroup.activeCount());
System.out.println("معلومات حول مجموعة الخيوط");
ThreadGroup.list();
11. استخدم activeCount() وenumerate() للحصول على عدد المواضيع النشطة في كائن ThreadGroup ونسخه إلى مصفوفة الخيوط. استخدم طريقة get*() للحصول على اسم وحالة الموضوع. الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
Thread[] threads = new Thread[threadGroup.activeCount()];
ThreadGroup.enumerate(threads);
for (int i = 0; i < threadGroup.activeCount(); i++) {
System.out.printf("الخيط %s: %s/n"، المواضيع[i].getName()،
المواضيع[i].getState());
}
12. اتصل بطريقة waitFinish () وانتظر حتى يكمل أحد سلاسل الرسائل الموجودة في كائن ThreadGroup المهمة. قم بتنفيذ هذه الطريقة لاحقًا. الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
waitFinish(threadGroup);
13. استخدم طريقة المقاطعة () لمقاطعة سلاسل الرسائل الأخرى في مجموعة سلاسل الرسائل. الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
ThreadGroup.interrupt();
14. قم بتنفيذ طريقة waitFinish () واستخدم طريقة activeCount () للتحكم في نتائج تنفيذ الخيط. الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
// انتظر حتى تكتمل المهمة
انتظار الفراغ الثابت الخاص (ThreadGroup threadGroup) {
بينما (threadGroup.activeCount() > 9) {
يحاول {
TimeUnit.SECONDS.sleep(1);
} قبض على (InterruptedException e) {
printStackTrace();
}
}
}
15. قم بتشغيل البرنامج وتحقق من تأثير التنفيذ.
أعرف لماذا
وفيما يلي نتيجة تنفيذ البرنامج. سترى مخرجات طريقة القائمة () وحالة كل موضوع وما إلى ذلك.
انسخ رمز الكود كما يلي:
الموضوع الموضوع-0: ابدأ
الموضوع الموضوع-0: 52
الموضوع الموضوع-1: ابدأ
الموضوع-1: 41
الموضوع الموضوع-2: ابدأ
موضوع-2: 69
الموضوع الموضوع-3: ابدأ
الموضوع-3: 60
الموضوع الموضوع-4: ابدأ
الموضوع-4: 88
عدد المواضيع: 5
معلومات حول مجموعة المواضيع
java.lang.ThreadGroup[name=Searcher,maxpri=10]
الموضوع[الموضوع-0،5،الباحث]
الموضوع[الموضوع-1،5،الباحث]
الموضوع[الموضوع-2،5،الباحث]
الموضوع[الموضوع-3،5،الباحث]
الموضوع[الموضوع-4،5،الباحث]
الموضوع-0: TIMED_WAITING
موضوع الموضوع-1: TIMED_WAITING
موضوع الموضوع-2: TIMED_WAITING
موضوع الموضوع-3: TIMED_WAITING
الموضوع-4: TIMED_WAITING
مؤشر الترابط-1: تمت مقاطعته
الموضوع-4: تمت مقاطعته
الموضوع الموضوع-2: تمت مقاطعته
مؤشر الترابط-0: تمت مقاطعته
الموضوع-3: تمت مقاطعته
تقوم فئة ThreadGroup بتخزين العديد من كائنات Thread وكائنات ThreadGroup المرتبطة بها. يمكنك الوصول إلى معلومات مؤشر الترابط عن طريق استدعاء أساليب هذه الفئة، ويمكنك أيضًا إجراء عمليات مختلفة عليها، مثل المقاطعات.
لا تنتهي أبدا
تحتوي فئة ThreadGroup أيضًا على العديد من الطرق. يرجى قراءة وثائق API للحصول على أوصاف الطريقة الكاملة.
استخدام العقيدة
تمت ترجمة هذه المقالة من "Java 7 Concurrency Cookbook" (سرقها D Gua Ge باسم "مجموعة أمثلة Java7 Concurrency") ويتم استخدامها فقط كمواد تعليمية. ولا يجوز استخدامه لأية أغراض تجارية دون تصريح.
نجاح صغير
يوجد أدناه الإصدار الكامل من التعليمات البرمجية المستخدمة في الأمثلة الموجودة في هذا القسم.
الرمز الكامل لفئة النتيجة:
انسخ رمز الكود كما يلي:
الحزمة com.diguage.books.concurrencycookbook.chapter1.recipe10؛
/**
* نتائج الاستعلام مخزن
* التاريخ: 2013-09-30
*التوقيت: 00:45
*/
نتيجة الطبقة العامة {
اسم سلسلة خاصة؛
سلسلة عامة getName () {
اسم الإرجاع؛
}
اسم مجموعة الفراغ العام (اسم السلسلة) {
this.name = name;
}
}
الكود الكامل لفئة SearchTask هو كما يلي:
الحزمة com.diguage.books.concurrencycookbook.chapter1.recipe10؛
import java.util.Date;
import java.util.Random;
import java.util.concurrent.TimeUnit;
/**
* فئة البحث المحاكاة
* التاريخ: 2013-10-02
*الزمن: 22:38
*/
فئة عامة SearchTask تنفذ Runnable {
نتيجة النتيجة الخاصة؛
مهمة البحث العامة (نتيجة النتيجة) {
this.result = result;
}
@تجاوز
تشغيل الفراغ العام () {
اسم السلسلة = Thread.currentThread().getName();
System.out.printf("الموضوع %s: البدء/n"، الاسم)؛
يحاول {
doTask();
result.setName(name);
} قبض على (InterruptedException e) {
System.out.printf("مؤشر الترابط %s: تمت مقاطعته/n"، name);
يعود؛
}
System.out.printf("الموضوع %s: النهاية/n"، الاسم)؛
}
// محاكاة البحث
doTask () الخاص باطلة يلقي InterruptedException {
عشوائي عشوائي = عشوائي جديد (تاريخ جديد ().getTime ())؛
int value = (int) (random.nextDouble() * 100);
System.out.printf("مؤشر الترابط %s: %d/n"،
Thread.currentThread().getName(), value);
TimeUnit.SECONDS.sleep(value);
}
}
الكود الكامل للفئة الرئيسية:
انسخ رمز الكود كما يلي:
الحزمة com.diguage.books.concurrencycookbook.chapter1.recipe10؛
import java.util.concurrent.TimeUnit;
/**
* مثال مجموعة الموضوع الفئة الرئيسية
* التاريخ: 2013-10-02
*الساعة: 22:45
*/
الطبقة العامة الرئيسية {
public static void main(String[] args) {
ThreadGroup threadGroup = new ThreadGroup("Searcher");
نتيجة النتيجة = نتيجة جديدة ()؛
SearchTask searchTask = new SearchTask(result);
لـ (int i = 0; i < 5; i++) {
Thread thread = new Thread(threadGroup, searchTask);
Thread.start();
يحاول {
TimeUnit.SECONDS.sleep(1);
} قبض على (InterruptedException e) {
printStackTrace();
}
}
System.out.printf("عدد المواضيع: %d/n"، threadGroup.activeCount());
System.out.println("معلومات حول مجموعة الخيوط");
ThreadGroup.list();
Thread[] threads = new Thread[threadGroup.activeCount()];
ThreadGroup.enumerate(threads);
for (int i = 0; i < threadGroup.activeCount(); i++) {
System.out.printf("الخيط %s: %s/n"، المواضيع[i].getName()،
المواضيع[i].getState());
}
waitFinish(threadGroup);
ThreadGroup.interrupt();
}
// انتظر حتى تكتمل المهمة
انتظار الفراغ الثابت الخاص (ThreadGroup threadGroup) {
بينما (threadGroup.activeCount() > 9) {
يحاول {
TimeUnit.SECONDS.sleep(1);
} قبض على (InterruptedException e) {
printStackTrace();
}
}
}
}