انتظر المشهد
يرتبط مشهد الانتظار النموذجي بشكل عام بالمحتلين التاليين:
1. متغير الدولة
عندما تحتاج المواضيع إلى الانتظار ، يكون سببها دائمًا بعض الظروف. على سبيل المثال ، ملء قائمة الانتظار ، عندما يكون عنصر قائمة الانتظار ممتلئًا ، يحتاج مؤشر الترابط إلى التوقف عن التشغيل. عندما تكون عناصر قائمة الانتظار شاغرة ، تابع تنفيذها.
2. شرط المسند
عندما يتم تحديد مؤشر الترابط ما إذا كان سيتم إدخال الانتظار أو الاستيقاظ من الإخطار ، فمن الضروري اختبار ما إذا كانت شروط الحالة قد تم استيفاءها. على سبيل المثال ، إضافة عناصر إلى قائمة الانتظار ، تكون قائمة الانتظار ممتلئة ، بحيث تمنع الخيط الحالي. خيط." في هذا الوقت ، سيتم إيقاظ عملية الانتظار للعنصر ، ثم تحكم على ما إذا كان هناك مجال لقائمة الانتظار الحالية. الاستيقاظ التالي.
3. قائمة انتظار الحالة
يحتوي كل كائن على قائمة انتظار شرطية مدمجة.
يلاحظ
الانتظار والإخطار جزء مهم من آلية مزامنة Java. إلى جانب استخدام الكلمات الرئيسية المتزامنة ، يمكن إنشاء العديد من النماذج المتزامنة الممتازة ، مثل نموذج المنتج المستهلك. ولكن عند استخدام الوظيفة () ، الإخطار () ، الإخطار () ، تحتاج إلى إيلاء اهتمام خاص للنقاط التالية:
انتظر () ، إخطار () ، أساليب الإخطار () لا تنتمي إلى فئة مؤشرات الترابط ، ولكنها تنتمي إلى فئة مؤسسة الكائن ، أي أن كل كائن له وظائف Wait () ، والإخطار () ، والإخطار (). نظرًا لأن كل كائن مغلق ، فإن القفل هو أساس كل كائن ، وبالتالي فإن طريقة تشغيل القفل هي أيضًا الأكثر أساسية.
استدعاء OBJ WAIT () وأسلوب الإخطار () ، يجب أن تحصل على قفل OBJ ، أي ، يجب أن تكون مكتوبًا في قطاع الكود المتزامن (OBJ) {...}.
بعد استدعاء OBJ.WAIT () ، يقوم مؤشر الترابط A بإصدار قفل OBJ ، وإلا فإن الخيط B لا يمكنه الحصول على قفل OBJ ، ولن يكون قادرًا على إيقاظ مؤشر الترابط A في رمز متزامن (OBJ) {...} شريحة.
عند إرجاع طريقة OBJ.WAIT () ، يحتاج الموضوع A إلى الحصول على قفل OBJ مرة أخرى لمتابعة التنفيذ.
إذا كانت المواضيع A1 و A2 و A3 في OBJ.WAIT () ، فإن الخيط B يستدعي OBJ.Notify () يمكن أن يستيقظ فقط أحد المواضيع A1 و A2 و A3 (التي يتم تحديدها بواسطة JVM).
إذا استدعى الموضوع B OBJ.Notifyall () ، فيمكنه جميعًا أن يستيقظ مؤشر ترابط الانتظار A1 و A2 و A3 ، ولكن موضوع الانتظار لمواصلة تنفيذ الجملة التالية لـ OBJ.WAIT () ، يجب أن تحصل على قفل OBJ. لذلك ، فإن الخيوط A1 و A2 و A3 لديها فرصة واحدة فقط للحصول على الأقفال والاستمرار في التنفيذ.
عندما يستدعي الموضوع B OBJ.Notify () أو OBJ.NotifyAll () ، فإن الموضوع B يحمل قفل OBJ. إلى أن يخرج مؤشر الترابط B من كتلة الكود المتزامن وإطلاق قفل OBJ ، يتمتع واحد في الخيط A1 و A2 و A3 بفرصة الحصول على قفل الكائن والمتابعة للتنفيذ.
على سبيل المثال رمز
هيكل الكود النموذجي لعملية انتظار مؤشر الترابط كما يلي:
اختبار void العام () يلقي interruptedException {Synchronized (obj) {بينما (! contidition) {obj.wait () ؛}}}}}}}}}}
لماذا يجب أن تكون عمليات OBJ.WAIT () موجودة في الدورة؟ هناك عدة أسباب رئيسية:
1. يمكن استخدام قفل الكائن لحماية متغيرات الحالة المتعددة. على سبيل المثال ، يقوم كائن معين بحماية متغيرات الحالة A و B. عند عدم تأسيس شروط التأكيد ، تحدث عملية الانتظار. الآن إذا حدث تشغيل متغير الحالة A ، يتم استدعاء عملية الإخطار على OBJ ، ثم يتم إيقاف جميع المواضيع في قائمة انتظار الشرط التي تتوافق مع OBJ. من أجل استيقظ أيضًا في هذا الوقت ، لذلك تحتاج إلى إعادة تدوير ما إذا كان يتم الوفاء بحالة B ليتم الوفاء بها.
2. يتم تأكيد شروط نفس حالة الخيوط المتعددة. على سبيل المثال ، مشهد إضافة عناصر إلى قائمة الانتظار ، فإن قائمة الانتظار الحالية ممتلئة ، وتريد عدة مؤشرات ترابط إضافة عناصر إلى الداخل ، لذلك كلها. في هذا الوقت ، أخرج مؤشر ترابط آخر عنصرًا من قائمة الانتظار ودعا عملية الإخطار لإيقاظ جميع المواضيع ، ولكن لا يزال هناك حاجة إلى موضوع واحد فقط.
3. صحوة كاذبة. دون إخطار ، مقاطعة orout ، تم إيقاظ الموضوع تلقائيا. على الرغم من أن هذا الموقف نادراً ما يحدث في الممارسة العملية ، إلا أنه يمكن القضاء على هذا الموقف من خلال انتظار الدورة.