استخدم WAIT () وأبلغ () لتحقيق التعاون بين الخيوط
1. انتظر () وأخطئ ()/إخطار ()
عندما يتم استدعاء Sleep () والعائد () ، لا يتم إطلاق القفل ، وسيقوم الاتصال بالاتصال () إلى إطلاق القفل. وبهذه الطريقة ، يمكن لمهمة أخرى (مؤشر ترابط) الحصول على قفل الكائن الحالي ، وبالتالي إدخال طريقته المتزامنة. يمكنك استئناف التنفيذ من WAIT () من خلال إخطار ()/إخطار () أو انتهاء صلاحية الوقت.
لا يمكن استدعاء () وانتظر () ، إخطار () ، وإخطار () إلا في طريقة التحكم في المزامنة أو كتلة التزامن. إذا تم استدعاء هذه الأساليب بطريقة غير متزامنة ، فسيتم إلقاء استثناء غير شرعي في وقت التشغيل.
2. محاكاة إيقاظ مؤشرات ترابط متعددة بخيط واحد
محاكاة التعاون بين المواضيع. يحتوي فئة اللعبة على طريقين للمزامنة إعداد () و GO (). يتم استخدام بدء العلم لتحديد ما إذا كان الخيط الحالي يحتاج إلى WAIT (). يبدأ مثيل فئة اللعبة جميع مثيلات فئة Athele أولاً وأدخل حالة Wait (). بعد فترة من الزمن ، قم بتغيير بت العلم وإخطار () جميع خيوط Athele في حالة الانتظار.
game.java
حزمة التزامن ؛ استيراد java.util.collection ؛ استيراد java.util.collections ؛ استيراد java.util.hashset ؛ استيراد java.util.iterator ؛ استيراد java.util.set ؛ فئة رياضي يدير {private final in id ؛ لعبة اللعبة الخاصة الرياضي العام (int id ، لعبة اللعبة) {this.id = id ؛ this.game = لعبة ؛ } منطقية عامة يساوي (كائن O) {if (! (o extueof sthoote)) إرجاع false ؛ رياضي رياضي = (رياضي) o ؛ معرف الإرجاع == ATTHE.ID ؛ } السلسلة العامة toString () {return "Athlete <" + id + ">" ؛ } public int hashcode () {return new integer (id) .hashCode () ؛ } public void run () {try {game.prepare (this) ؛ } catch (interruptedException e) {system.out.println (this + "Quit the Game") ؛ }}} تنفذ لعبة الفئة العامة runnable {private set <Thative> players = new hashset <ThateRe> () ؛ بداية منطقية خاصة = خطأ ؛ public void addPlayer (Athlete One) {players.add (one) ؛ } public void removePlayer (Athlete One) {players.remove (one) ؛ } مجموعة عامة <ThateRe> getPlayers () {return collections.unmodifiableset (players) ؛ } public void إعداد (رياضي رياضي) يلقي InterruptedException {system.out.println (Athlete + "Ready!") ؛ متزامن (هذا) {بينما (! start) wait () ؛ if (start) system.out.println (Athlete + "Go!") ؛ }} void synchronized synchronized go () {eletifyAll () ؛ } void public ready () {iterator <Thatere> iter = getPlayers (). iterator () ؛ بينما (iter.hasnext ()) موضوع جديد (iter.next ()). start () ؛ } public void run () {start = false ؛ System.out.println ("جاهز ...") ؛ System.out.println ("جاهز ...") ؛ System.out.println ("جاهز ...") ؛ مستعد()؛ ابدأ = صحيح ؛ System.out.println ("GO!") ؛ يذهب()؛ } public static void main (string [] args) {game game = new game () ؛ لـ (int i = 0 ؛ i <10 ؛ i ++) game.addplayer (New Athlete (i ، game)) ؛ موضوع جديد (لعبة) .start () ؛ }} نتيجة:
جاهز ... جاهز ... جاهز ... رياضي <0> جاهز! رياضي <1> جاهز! رياضي <2> جاهز! رياضي <3> جاهز! رياضي <4> جاهز! رياضي <5> جاهز! رياضي <6> جاهز! رياضي <7> جاهز! اذهب! رياضي <3> اذهب! رياضي <2> اذهب! رياضي <1> اذهب! رياضي <0> اذهب!
3. محاكاة عملية الانتظار المزدحمة
مثال على فئة MyObject هو المراقب. عند حدوث حدث مراقبة ، سيخطر مثيل بفئة الشاشة (بالطريقة التي يتم بها تغيير العلم). يتحقق مثيل فئة الشاشة هذه باستمرار ما إذا كان بتة العلم تتغير عن طريق الانتظار.
مشغول wavaing.java
استيراد java.util.concurrent.timeUnit ؛ class myobject تنفذ Runnable {private monitor monitor ؛ Public MyObject (Monitor Monitor) {this.monitor = monitor ؛ } public void run () {try {timeUnit.seconds.sleep (3) ؛ system.out.println ("أنا ذاهب.") ؛ monitor.gotmessage () ؛ } catch (interruptedException e) {E.PrintStackTrace () ؛ }}} فئة مراقبة الفئة تنفذ Runnable {private folatile boolean go = false ؛ public void gotmessage () رميات interruptedException {go = true ؛ } public void watch () {بينما (go == false) ؛ system.out.println ("لقد ذهب.") ؛ } public void run () {watch () ؛ }} الفئة العامة مشغول waiting {public static void main (string [] args) {monitor monitor = new monitor () ؛ myobject o = new myobject (monitor) ؛ موضوع جديد (O) .start () ؛ موضوع جديد (شاشة) .start () ؛ }} نتيجة:
أنا ذاهب. لقد ذهب.
4. استخدم WAIT () وأبلغ () لإعادة كتابة المثال أعلاه
يحل المثال التالي محل آلية الانتظار المزدحمة من خلال Wait (). عند تلقي رسالة إخطار ، قم بإخطار مؤشر ترابط فئة الشاشة الحالية.
انتظر
حزمة concurrency.wait ؛ استيراد java.util.concurrent.TimeUnit ؛ فئة myobject تنفذ Runnable {private monitor ؛ Public MyObject (Monitor Monitor) {this.monitor = monitor ؛ } ابدأ الموضوع بانتظام
فيما يلي طريقتان لبدء موضوع بعد وقت محدد. أولاً ، يتم تنفيذها من خلال java.util.concurrent.delayqueue ؛ ثانياً ، يتم تنفيذها من خلال java.util.concurrent.scheduledthreadpoolexecutor.
1. java.util.concurrent.delayqueue
إن تأخير الفصل هو قائمة انتظار حظر غير محدودة يمكن من خلالها استخراج العناصر فقط عندما ينتهي التأخير. يقبل الحالات التي تنفذ الواجهة المتأخرة كعناصر.
<< واجهة >> تأخير. java
package java.util.concurrent ؛ استيراد java.util.*؛ الواجهة العامة المتأخرة تمتد قابلة للمقارنة <ghended> {long getDelay (وحدة TimeUnit) ؛}GetDelay () يعيد وقت التأخير المتبقي المرتبط بهذا الكائن ، المعبر عنه في وحدات الوقت المحددة. يجب أن يحدد تنفيذ هذه الواجهة طريقة المقارنة التي توفر نوعًا ثابتًا مع طريقة getDelay لهذه الواجهة.
رأس قائمة انتظار التأخير هو العنصر المتأخر مع أطول وقت تخزين بعد انتهاء صلاحية التأخير. يحدث انتهاء الصلاحية عندما تقوم طريقة getDelay (timeUnit.nanoseconds) بعنصر بإرجاع قيمة أقل من أو تساوي 0.
2. طوابير التصميم مع خصائص تأخير الوقت
يحتفظ Class PervideDedTasker بقائمة قائمة انتظار تأخير <DeveledDtask> ، حيث يقوم التأخير بتنفيذ الواجهة المتأخرة ويتم تعريفه بواسطة فئة داخلية. تنفذ كل من الفئات الخارجية والفئات الداخلية واجهة Runnable. بالنسبة للفئات الخارجية ، تأخذ طريقة التشغيل المهام في قائمة الانتظار بالتسلسل وفقًا للوقت المحدد ، وهذه المهام هي حالات من الفئات الداخلية. تحدد طريقة تشغيل الفئات الداخلية المنطق المحدد لكل مؤشر ترابط.
يتمثل جوهر هذا التصميم في تحديد قائمة مهام الخيوط مع خصائص الوقت ، ويمكن أن تكون القائمة من أي طول. حدد وقت بدء التشغيل في كل مرة تضيف فيها مهمة.
تأخير assasker.java
package com.zj.timedtask ؛ استيراد java.util.concurrent.timeunit.seconds ؛ استيراد java.util.concurrent.timeunit.nanoseconds ؛ java.util.concurrent.delayed ؛ import java.util.concurrent.executorservice ؛ import java.util.concurrent.executors ؛ استيراد java.util.concurrent.timeUnit ؛ public addrastasker pyricments {delayqueue <dilledtask> public void addTask (تأخير e) {queue.put (e) ؛ } public void removetask () {queue.poll () ؛ } المجموعة العامة <GeveredTask> getAlltasks () {return collections.unmodifiableCollection (Queue) ؛ } public int getTaskQuantity () {return queue.size () ؛ } public void run () {when (! queue.isempty ()) حاول {queue.take (). run () ؛ } catch (interruptedException e) {system.out.println ("interrupted") ؛ } system.out.println ("intededDtask") ؛ } تنفذ الفئة الثابتة العامة التي تأخرت ، قابلة للتشغيل {private static int counter = 0 ؛ معرف int النهائي الخاص = counter ++ ؛ دلتا النهائي الخاص الزناد النهائي الطويل الخاص ؛ Public LeveledTask (int DelayInseconds) {Delta = DelayInseconds ؛ trigger = system.nanotime () + nanoseconds.convert (Delta ، Seconds) ؛ } public getDelay (وحدة timeUnit) {return unit.convert (trigger - system.nanotime () ، nanoSeconds) ؛ } public int compareto (تأخير arg) {delayedTask that = (eventedTask) arg ؛ if (trigger <that.trigger) return -1 ؛ if (trigger> that.trigger) return 1 ؛ العودة 0 ؛ } public void run () {// قم بتشغيل كل ما تريد القيام به system.out.println (هذا) ؛ } السلسلة العامة toString () {return "[" + delta + "s]" + "task" + id ؛ }} public static void main (string [] args) {random rand = new Random () ؛ ExecutorService exec = Executors.NewCacheDthReadPool () ؛ تأخير assactasker = تأخير جديد adgentTasker () ؛ لـ (int i = 0 ؛ i <10 ؛ i ++) tasker.addtask (تأخير جديد (rand.nextint (5))) ؛ exec.execute (Tasker) ؛ exec.shutdown () ؛ }} نتيجة:
[0S] المهمة 1 [0S] المهمة 2 [0S] المهمة 3 [1S] المهمة 6 [2S] المهمة 5 [3S] المهمة 8 [4S] المهمة 0 [4S] المهمة 4 [4S] المهمة 7 [4S] المهمة 9finishedDelayedTask
3. java.util.concurrent.scheduledthreadpoolexecutor
يمكن جدولة هذه الفئة لتشغيل المهام (مؤشرات الترابط) بعد تأخير معين ، أو لأداء المهام بانتظام (كرر). في المنشئ ، تحتاج إلى معرفة حجم تجمع الخيوط. الطريقة الرئيسية هي:
[1] الجدول الزمني
الجدول العام <؟> الجدول الزمني (القيادة القابلة للتشغيل ، التأخير الطويل ، وحدة الوقت)
يقوم بإنشاء وتمكين عملية لمرة واحدة بعد تأخير معين.
المعين من قبل:
- الجدول الزمني في واجهة SchedulexecutorService ؛
المعلمة:
-Command - المهمة التي يتعين تنفيذها ؛
-delay - وقت تأخير التنفيذ من الآن فصاعدًا ؛
-unit - وحدة الوقت لمعلمات التأخير ؛
يعود:
- يشير إلى أن الجدولة التي تعلق المهمة وطريقة GET () ستعود خالية بعد الانتهاء.
[2] ScheduleAtfixedrate
ScheduleAtFixedRate ScheduledFuture العامة (
أمر Runnable ، initialdelay الطويل ، الفترة الطويلة ، وحدة TimeUnit)
قم بإنشاء وتنفيذ عملية دورية يتم تمكينها لأول مرة بعد تأخير أولي معين ، مع وجود عمليات لاحقة ؛ أي أنه سيبدأ بعد internaldelay ، ثم بعد الفترة initialDelay + ، ثم بعد فترة initialdelay + 2 * ، وهكذا. إذا واجه أي تنفيذ لمهمة استثناء ، فسيتم إلغاء التنفيذ اللاحق. خلاف ذلك ، لا يمكن إنهاء المهمة إلا من خلال تنفيذ طريقة الإلغاء أو إنهاء البرنامج. إذا استغرق أي من عمليات الإعدام لهذه المهمة وقتًا أطول من دورتها ، فسيتم تأجيل التنفيذ اللاحق ، ولكن ليس في وقت واحد.
المعين من قبل:
- ScheduleAtfixedrate في واجهة ScreduDexecutorService ؛
المعلمة:
-Command - المهمة التي يتعين تنفيذها ؛
-initialdelay - وقت التأخير للتنفيذ الأول ؛
-Period - الفترة بين عمليات الإعدام المستمرة ؛
-unit - الوحدة الزمنية للمعلمات الأولية ومعلمات الفترة ؛
يعود:
- يشير إلى أن جدولة المهمة المعلقة قد اكتملت ، وسيقوم طريقة GET () بإلقاء استثناء بعد إلغاؤها.
4. تصميم سلاسل الرسائل مع خصائص تأخير الوقت
يربط Class ScheduleTasked A SecretThReadPoolexCutor ، والذي يمكنه تحديد حجم تجمع الخيوط. تعرف على خيط وتأخير وقت من خلال طريقة الجدول ، وأغلق تجمع الخيوط من خلال طريقة إيقاف التشغيل. منطق المهام المحددة (مؤشرات الترابط) له مرونة معينة (مقارنة بالتصميم السابق ، يجب أن يحدد التصميم السابق منطق مؤشر الترابط مقدمًا ، ولكن يمكن تعديل تصميم المنطق المحدد للموضوع عن طريق الميراث أو الزخرفة).
ScheduleTasker.java
package com.zj.timedTask ؛ import java.util.concurrent.scheduledthreadpoolexecutor ؛ import java.util.concurrent.timeunit ؛ scheduletasker public {private int corepoolsize = 10 ؛ SchedulthReadPoolexecutor Scheduler ؛ ScheduleTasker () {Scheduler = new SecretThreadPoolExecutor (CorePoolSize) ؛ } ScheduleTasker (int int) {corePoolSize = Quantity ؛ SCHELLER = جديد SCHEDULEDTHREADPOOLEXECUTOR (corePoolSize) ؛ } جدول الفراغ العام (حدث Runnable ، تأخير طويل) {Scheduler.Schedule (الحدث ، التأخير ، timeunit.seconds) ؛ } public void sthowddown () {Scheduler.Shutdown () ؛ } public static void main (string [] args) {ScheduleTasker tasker = new ScheduleTasker () ؛ Tasker.Schedule (new RunNable () {public void run () {system.out.println ("[1S] Task 1") ؛}} ، 1) ؛ Tasker.Schedule (New RunNable () {public void run () {system.out.println ("[2S] Task 2") ؛}} ، 2) ؛ Tasker.Schedule (new RunNable () {public void run () {system.out.println ("[4S] Task 3") ؛}} ، 4) ؛ Tasker.Schedule (new RunNable () {public void run () {public void run () {system.out.println ("[10S] Task 4") ؛}} ، 10) ؛ Tasker.Shutdown () ؛ }} نتيجة:
[1S] المهمة 1 [2S] المهمة 2 [4S] المهمة 3 [10s] المهمة 4 باطلة عامة Run () {try {timeUnit.seconds.sleep (3) ؛ system.out.println ("أنا ذاهب.") ؛ monitor.gotmessage () ؛ } catch (interruptedException e) {E.PrintStackTrace () ؛ }}} مراقبة الفئة تنفذ runnable {private polatile boolean go = false ؛ رميات gotmessage المزامنة العامة () interruptedException {go = true ؛ إخطار () ؛ } رميات الفراغ المزامنة العامة () رميات interruptedException {بينما (go == false) wait () ؛ system.out.println ("لقد ذهب.") ؛ } public void run () {try {watch () ؛ } catch (interruptedException e) {E.PrintStackTrace () ؛ }}} الفئة العامة wait {public static void main (string [] args) {monitor monitor = new monitor () ؛ myobject o = new myobject (monitor) ؛ موضوع جديد (O) .start () ؛ موضوع جديد (شاشة) .start () ؛ }} نتيجة:
أنا ذاهب. لقد ذهب.