في بعض السيناريوهات، يجب علينا الانتظار حتى يكتمل تنفيذ الخيط قبل المتابعة إلى الخطوة التالية. على سبيل المثال، تحتاج بعض البرامج إلى تهيئة بعض الموارد قبل بدء التنفيذ. في هذا الوقت، يمكننا بدء سلسلة محادثات خصيصًا للقيام بمهمة التهيئة، والانتظار حتى تكتمل مهمة سلسلة الرسائل قبل تنفيذ الأجزاء الأخرى.
لهذا الغرض، توفر لنا فئة Thread طريقة join(). عندما نستدعي هذه الطريقة باستخدام كائن مؤشر ترابط، سيتم تأخير كائن مؤشر الترابط المستدعي حتى يكتمل تنفيذ الكائن المستدعى قبل بدء التنفيذ.
في هذا القسم، يوضح نموذج البرنامج انتظار اكتمال أسلوب التهيئة قبل تنفيذ مهام أخرى.
تعرف عليه
اتبع الخطوات الموضحة أدناه لإكمال نموذج البرنامج.
1. قم بإنشاء فئة باسم DataSourcesLoader وقم بتنفيذ الواجهة القابلة للتشغيل. الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
فئة عامة DataSourcesLoader تنفذ Runnable {
2. قم بتنفيذ طريقة التشغيل () وطباعة رسالة إلى وحدة التحكم للإشارة إلى بداية التنفيذ، ثم النوم لمدة 4 ثوانٍ، ثم طباعة رسالة إلى وحدة التحكم للإشارة إلى نهاية تنفيذ مؤشر الترابط. الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
@تجاوز
تشغيل الفراغ العام () {
System.out.printf ("بدء تحميل مصادر البيانات: %s/n"،
تاريخ جديد ())؛
يحاول {
TimeUnit.SECONDS.sleep(4);
} قبض على (InterruptedException e) {
printStackTrace();
}
System.out.printf("انتهى تحميل مصادر البيانات: %s/n"،
تاريخ جديد ())؛
}
3. قم بإنشاء فئة باسم NetworkConnectionsLoader وقم بتنفيذ الواجهة القابلة للتشغيل. قم بتنفيذ طريقة run()، رمز هذه الطريقة هو نفس طريقة run() لفئة DataSourcesLoader، باستثناء أنه ينام لمدة 6 ثوانٍ.
4. قم بتنفيذ الفئة الرئيسية للمثال وقم بتنفيذ الطريقة الرئيسية (). الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
الطبقة العامة الرئيسية {
public static void main(String[] args) {
5. قم بإنشاء كائن DataSourcesLoader وكائن Thread لبدء تنفيذه. الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
DataSourcesLoader dsLoader = new DataSourcesLoader();
Thread thread1 = new Thread(dsLoader, "DataSourcesLoader");
6. قم بإنشاء كائن NetworkConnectionsLoader وكائن Thread لبدء تنفيذه. الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
NetworkConnectionsLoader ncLoader = new NetworkConnectionsLoader();
Thread thread2 = new Thread(ncLoader, "NetworkConnectionsLoader");
7. قم باستدعاء طريقة start () لكائني Thread. الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
Thread1.start();
Thread2.start();
8. اتصل بالطريقة join() لانتظار الخيطين لإكمال مهامهما. ستطرح هذه الطريقة InterruptedException، لذا التقط هذا الاستثناء. الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
يحاول {
Thread1.join();
Thread2.join();
} قبض على (InterruptedException e) {
printStackTrace();
}
9. اطبع جملة على لوحة التحكم للإشارة إلى نهاية تنفيذ البرنامج. الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
System.out.printf("الرئيسي: تم تحميل التكوين: %s/n"،
تاريخ جديد ())؛
10. قم بتشغيل البرنامج وتحقق من تأثير التنفيذ.
أعرف لماذا
عند تشغيل هذا البرنامج النموذجي، يمكننا أن نرى خيطين يبدأان في التنفيذ. أولاً، يكمل DataSourcesLoader تنفيذه، ثم يكمل NetworkConnectionsLoader تنفيذه. عند هذه النقطة، يواصل مؤشر الترابط الرئيسي تنفيذه ثم يطبع رسالة إنهاء إلى وحدة التحكم.
لا تنتهي أبدا
توفر Java طريقتين أخريين للانضمام () محملتين بشكل زائد:
انسخ رمز الكود كما يلي:
الانضمام (ملي ثانية طويلة)
الانضمام (ملي ثانية طويلة، نانو طويلة)
الطريقة الأولى لا تنتظر حتى يتم الاستدعاء لإكمال المهمة، ولكنها تنتظر الوقت المحدد بواسطة المعلمة قبل بدء التنفيذ، على سبيل المثال، إذا استدعى Thread1 هذه الطريقة، thread1.join(1000)، عندما يلتقي مؤشر الترابط thread1 بأحدها سيستمر تنفيذ الشروط التالية:
1.thread2 يكمل تنفيذه؛
2. بعد 1000 ميلي ثانية؛
عندما يتحقق أحد هذين الشرطين، ستعود طريقة join() وتستمر في تنفيذ المهمة الأصلية.
الطريقة الثانية تشبه إلى حد كبير الطريقة الأولى، إلا أنها تحتوي على معلمة زمنية إضافية بالنانو ثانية.
استخدام العقيدة
تمت ترجمة هذه المقالة من "Java 7 Concurrency Cookbook" (سرقها D Gua Ge باسم "مجموعة أمثلة Java7 Concurrency") ويتم استخدامها فقط كمواد تعليمية. ولا يجوز استخدامه لأية أغراض تجارية دون تصريح.
نجاح صغير
النسخة الكاملة من نموذج التعليمات البرمجية المستخدم في هذا القسم.
الكود الكامل لفئة DataSourcesLoader هو كما يلي:
الحزمة com.diguage.books.concurrencycookbook.chapter1.recipe6؛
import java.util.Date;
import java.util.concurrent.TimeUnit;
/**
* التاريخ: 2013-09-19
*التوقيت: 09:15
*/
الطبقة العامة DataSourcesLoader تنفذ Runnable {
@تجاوز
تشغيل الفراغ العام () {
System.out.printf ("بدء تحميل مصادر البيانات: %s/n"،
تاريخ جديد ())؛
يحاول {
TimeUnit.SECONDS.sleep(4);
} قبض على (InterruptedException e) {
printStackTrace();
}
System.out.printf("انتهى تحميل مصادر البيانات: %s/n"،
تاريخ جديد ())؛
}
}
الكود الكامل لفئة NetworkConnectionsLoader
انسخ رمز الكود كما يلي:
الحزمة com.diguage.books.concurrencycookbook.chapter1.recipe6؛
import java.util.Date;
import java.util.concurrent.TimeUnit;
/**
* التاريخ: 2013-09-19
*التوقيت: 09:21
*/
الطبقة العامة NetworkConnectionsLoader تنفذ Runnable {
@تجاوز
تشغيل الفراغ العام () {
System.out.printf ("بدء تحميل مصادر البيانات: %s/n"،
تاريخ جديد ())؛
يحاول {
TimeUnit.SECONDS.sleep(6);
} قبض على (InterruptedException e) {
printStackTrace();
}
System.out.printf("انتهى تحميل مصادر البيانات: %s/n"،
تاريخ جديد ())؛
}
}
الكود الكامل للفئة الرئيسية
انسخ رمز الكود كما يلي:
الحزمة com.diguage.books.concurrencycookbook.chapter1.recipe6؛
import java.util.Date;
/**
* التاريخ: 2013-09-19
*التوقيت: 09:25
*/
الطبقة العامة الرئيسية {
public static void main(String[] args) {
DataSourcesLoader dsLoader = new DataSourcesLoader();
Thread thread1 = new Thread(dsLoader, "DataSourcesLoader");
NetworkConnectionsLoader ncLoader = new NetworkConnectionsLoader();
Thread thread2 = new Thread(ncLoader, "NetworkConnectionsLoader");
Thread1.start();
Thread2.start();
يحاول {
Thread1.join();
Thread2.join();
} قبض على (InterruptedException e) {
printStackTrace();
}
System.out.printf("الرئيسي: تم تحميل التكوين: %s/n"،
تاريخ جديد ())؛
}
}