التحليل الأكثر شمولاً لاستخدام Java Multithreading. إذا لم تكن قد أجريت بحثًا متعمقًا حول آلية Java Multithreading ، فيمكن أن تساعدك هذه المقالة بشكل أكثر شمولية على فهم المبادئ وطرق الاستخدام في Java Multithreading.
1. إنشاء موضوع
هناك طريقتان لإنشاء مؤشرات ترابط في Java: استخدام فئة مؤشرات الترابط واستخدام واجهة Runnable. عند استخدام واجهة Runnable ، تحتاج إلى إنشاء مثيل مؤشر ترابط. لذلك ، سواء كنت تقوم بإنشاء مؤشر ترابط من خلال فئة مؤشرات الترابط أو الواجهة القابلة للتشغيل ، يجب عليك إنشاء مثيل لفئة مؤشر الترابط أو فئة الفئة الفرعية. مُنشئ الموضوع:
الطريقة 1: ورث فئة الخيط والكتابة فوق طريقة التشغيل
الفئة العامة threaddemo1 {public static void main (string [] args) {demo d = new demo () ؛ D.Start () ؛ لـ (int i = 0 ؛ i <60 ؛ i ++) {system.out.println (thread.currentThRead (). getName ()+i) ؛ }}} class demo يمتد مؤشر الترابط {public void run () {for (int i = 0 ؛ i <60 ؛ i ++) {system.out.println (thread.currentThRead (). getName ()+i) ؛ }}}الطريقة 2:
الفئة العامة threaddemo2 {public static void main (string [] args) {demo2 d = new demo2 () ؛ الموضوع T = موضوع جديد (D) ؛ T.Start () ؛ لـ (int x = 0 ؛ x <60 ؛ x ++) {system.out.println (thread.currentThRead (). getName ()+x) ؛ }}} class demo2 تنفذ Runnable {public void run () {for (int x = 0 ؛ x <60 ؛ x ++) {system.out.println (thread.currentThread (). getName ()+x) ؛ }}}2. دورة حياة الخيوط
تمامًا مثلما يولد الناس ، والشيخوخة ، والمرض والموت ، يجب أيضًا أن تمر عبر أربع ولايات مختلفة: ابدأ (انتظر) ، الجري ، التعليق والتوقف. يمكن التحكم في جميع الحالات الأربع بطرق في فئة الخيط. فيما يلي طريقة تتعلق بهذه الحالات الأربع في فئة الخيط.
// ابدأ الموضوع
PublicVoid start () ؛
PublicVoid Run () ؛
// تعليق وتستيقظ المواضيع
استئناف PublicVoid () ؛ // لا ينصح بالاستخدام
تعليق publicvoid () ؛ // لا ينصح بالاستخدام
نوم PublicStaticVoid (ملليس الطويل) ؛
نوم PublicStaticVoid (Long Millis ، int nanos) ؛
// إنهاء الموضوع
PublicVoid Stop () ؛ // لا ينصح بالاستخدام
PublicVoid Interrupt () ؛
// احصل على حالة الموضوع
PublicBoolean Isalive () ؛
PublicBoolean IsInterrupted () ؛
PublicStaticBoolean مقاطعة () ؛
// طريقة الانضمام
Publicvoid Join () رميات InterruptedException ؛
بعد إنشاء مؤشر الترابط ، لا ينفذ الرمز في طريقة التشغيل على الفور ، ولكن في حالة انتظار. عندما يكون مؤشر الترابط في حالة انتظار ، يمكنك استخدام طريقة فئة مؤشرات الترابط لتعيين خصائص مختلفة من مؤشر الترابط ، مثل أولوية مؤشر الترابط (setPriority) ، اسم مؤشر الترابط (setName) ونوع مؤشر الترابط (setDaemon) ، إلخ.
بعد استدعاء طريقة البدء ، يبدأ مؤشر الترابط في تنفيذ الكود في طريقة التشغيل. يدخل الموضوع إلى حالة الجري. يمكنك استخدام طريقة isalive لفئة مؤشرات الترابط لتحديد ما إذا كان الخيط في حالة التشغيل. عندما يكون الخيط في حالة الجري ، يعود Isalive صحيحًا. عندما يعود Isalive خطأ ، قد يكون الخيط في حالة الانتظار أو في حالة التوقف. يوضح الرمز التالي التبديل بين الحالات الثلاث لإنشاء وتشغيل وتوقف مؤشرات الترابط ، وإخراج قيمة الإرجاع isalive المقابلة.
بمجرد أن يبدأ مؤشر الترابط في تنفيذ طريقة التشغيل ، لن يخرج مؤشر الترابط حتى يتم تنفيذ طريقة التشغيل. ومع ذلك ، أثناء تنفيذ مؤشر ترابط ، يمكن إيقاف مؤشر الترابط مؤقتًا بطريقتين. هاتان الطريقتان تعليقان والنوم. بعد تعليق الخيط مع تعليق ، يمكن إيقاظ الخيط من خلال طريقة الاستئناف. بعد استخدام النوم للنوم ، لا يمكن وضع الخيط إلا في الحالة الجاهزة بعد الوقت المحدد (بعد نوم الخيط ، قد لا يتم تنفيذ الخيط على الفور ، لكنه يدخل الحالة الجاهزة وينتظر النظام).
هناك شيئان يجب ملاحظتهما عند استخدام طريقة النوم:
1. طريقة النوم لها نموذجين overload. لا يمكن ضبط أحد نماذج التحميل الزائد على المللي ثانية فحسب ، بل يمكن أيضًا أن يكون النانوية (1،000،000 نانو ثانية تساوي 1 مللي ثانية). ومع ذلك ، لا يمكن أن تكون آلات Java Virtual على معظم منصات نظام التشغيل دقيقة للأنظمة النانوية ، لذلك إذا تم تعيين النانو ثانية للنوم ، فستأخذ جهاز Java Virtual الجهاز الأقرب إلى هذه القيمة.
2. عند استخدام طريقة النوم ، يجب عليك استخدام الرميات أو محاولة {...} catch {...}. نظرًا لأن طريقة التشغيل لا يمكن استخدام رميات ، يمكنك فقط استخدام Try {...} catch {...}. عندما ينام الخيط ، سوف يرمي النوم استثناءً من المقاطعات عند مقاطعة الخيط باستخدام طريقة المقاطعة. يتم تعريف طريقة النوم على النحو التالي:
نوم PublicStaticVoid (Millis الطويل)
نوم PublicStaticVoid (Long Millis ، Int Nanos)
هناك ثلاث طرق لإنهاء الموضوع.
1. استخدم علامة الخروج لجعل مخرج مؤشر الترابط بشكل طبيعي ، أي أن الخيط ينتهي عند اكتمال طريقة التشغيل.
2. استخدم طريقة التوقف لإنهاء مؤشر الترابط بقوة (لا ينصح هذه الطريقة لأن التوقف هو نفسه التعليق والاستئناف ، وقد يكون له أيضًا نتائج غير متوقعة).
3. استخدم طريقة المقاطعة لمقاطعة الخيط.
1. استخدم علامة الخروج لإنهاء الموضوع
عند تنفيذ طريقة التشغيل ، سيتم الخروج من الخيط. ولكن في بعض الأحيان لا تنتهي طريقة التشغيل أبدًا. على سبيل المثال ، استخدام مؤشرات الترابط للاستماع إلى طلبات العميل في برامج الخادم ، أو المهام الأخرى التي تتطلب معالجة الحلقة. في هذه الحالة ، عادة ما يتم وضع هذه المهام في حلقة ، مثل أثناء الحلقة. إذا كنت تريد تشغيل الحلقة إلى الأبد ، فيمكنك استخدامها بينما (صحيح) {...} للتعامل معها. ومع ذلك ، إذا كنت ترغب في جعل الحلقة المخرج في حالة خروج في حالة معينة ، فإن الطريقة الأكثر مباشرة هي تعيين علامة نوع منطقية والتحكم في ما إذا كانت الحلقة تخرج عن طريق تعيين هذه العلامة إلى صواب أو خطأ. فيما يلي مثال على إنهاء مؤشر ترابط باستخدام علامة الخروج.
تتمثل وظيفة طريقة الانضمام في تحويل مؤشر ترابط التنفيذ غير المتزامن إلى تنفيذ متزامن. وهذا يعني ، عندما يتم استدعاء طريقة بدء مثيل الخيط ، ستعود الطريقة على الفور. إذا كانت هناك حاجة إلى استخدام قيمة محسوبة بواسطة هذا الموضوع بعد استدعاء طريقة البدء ، فيجب استخدام طريقة الانضمام. إذا لم تستخدم طريقة الانضمام ، فلا يمكن ضمان أنه عند تنفيذ بيان وراء طريقة البدء ، سيتم تنفيذ مؤشر الترابط. بعد استخدام طريقة الانضمام ، لن يتم تنفيذ البرنامج حتى يخرج الخيط. يوضح الرمز التالي استخدام Join.
3. قضايا السلامة متعددة التربعات
سبب المشكلة: عندما تعمل عبارات متعددة على نفس مؤشر الترابط لمشاركة البيانات ، يقوم مؤشر ترابط واحد فقط بتنفيذ جزء من عبارات متعددة ، لكنه لم ينته من تنفيذها حتى الآن ، ويشارك مؤشر ترابط آخر في التنفيذ ، مما يؤدي إلى خطأ في مشاركة البيانات.
الحل: بالنسبة لبيانات متعددة تشارك البيانات مع عمليات متعددة ، يمكن تنفيذ مؤشر ترابط واحد فقط. أثناء عملية التنفيذ ، لا يتم تنفيذ مؤشرات الترابط الأخرى.
مزامنة كتل التعليمات البرمجية:
الفئة العامة threaddemo3 {public static void main (string [] args) {ticket t = new ticket () ؛ الموضوع T1 = مؤشر ترابط جديد (T ، "Window One") ؛ الموضوع T2 = مؤشر ترابط جديد (T ، "Window Two") ؛ الموضوع T3 = مؤشر ترابط جديد (T ، "Window Three") ؛ الموضوع T4 = مؤشر ترابط جديد (T ، "Window Four") ؛ t1.start () ؛ t2.start () ؛ t3.start () ؛ t4.start () ؛ }} تذكرة الفئة تنفذ Runnable {private int ticket = 400 ؛ public void run () {بينما (true) {synchronized (new Object ()) {try {thread.sleep (1) ؛ } catch (interruptedException e) {// todo catch catch e.printstacktrace () ؛ } if (ticket <= 0) break ؛ System.out.println (thread.currentThRead (). getName ()+"--- بيع"+تذكرة-) ؛ }}}}وظائف متزامنة
الفئة العامة threaddemo3 {public static void main (string [] args) {ticket t = new ticket () ؛ الموضوع T1 = مؤشر ترابط جديد (T ، "Window One") ؛ الموضوع T2 = مؤشر ترابط جديد (T ، "Window Two") ؛ الموضوع T3 = مؤشر ترابط جديد (T ، "Window Three") ؛ الموضوع T4 = مؤشر ترابط جديد (T ، "Window Four") ؛ t1.start () ؛ t2.start () ؛ t3.start () ؛ t4.start () ؛ }} تذكرة الفئة تنفذ RunNable {private int ticket = 4000 ؛ saleticket void المزامنة العامة () {if (ticket> 0) system.out.println (thread.currentThRead (). getName ()+"بيع"+تذكرة-) ؛ } public void run () {بينما (صحيح) {saleticket () ؛ }}}قفل الوظيفة المتزامن هو قفل وظيفة التزامن ثابت هو فئة
التواصل بين المواضيع
الفئة العامة threaddemo3 {public static void main (string [] args) {class person {public string name ؛ سلسلة جنسية خاصة ؛ مجموعة void العامة (اسم السلسلة ، سلسلة الجنس) {this.name = name ؛ this.gender = الجنس ؛ } public void get () {system.out.println (this.name+"...."+this.gender) ؛ }} الشخص النهائي p = شخص جديد () ؛ مؤشر ترابط جديد (جديد RunNable () {public void run () {int x = 0 ؛ بينما (صحيح) {if (x == 0) {p.set ("Zhang San" ، "male") ؛} else {p.set ("lili" ، "nv") ؛} x = (x+1) ٪ 2 ؛}}}}}}). start () ؛ مؤشر ترابط جديد (جديد RunNable () {public void run () {بينما (صحيح) {p.get () ؛}}}). start () ؛ }}/ *Zhang San .... ذكر Zhang San .... ذكر Lili .... nvlili .... ذكر Zhang San .... nvlili .... ذكر */تعديل الرمز أعلاه
الفئة العامة threaddemo3 {public static void main (string [] args) {class person {public string name ؛ سلسلة جنسية خاصة ؛ مجموعة void العامة (اسم السلسلة ، سلسلة الجنس) {this.name = name ؛ this.gender = الجنس ؛ } public void get () {system.out.println (this.name+"...."+this.gender) ؛ }} الشخص النهائي p = شخص جديد () ؛ مؤشر ترابط جديد (جديد RunNable () {public void run () {int x = 0 ؛ بينما (صحيح) {synchronized (p) {if (x == 0) {p.set ("Zhang San" ، "male") ؛} else {p.set ("lili" ، "nv") ؛ مؤشر ترابط جديد (جديد RunNable () {public void run () {بينما (صحيح) {synchronized (p) {p.get () ؛}}}}}). start () ؛ }} /* lili .... nv lili .... nv lili .... nv lili .... nv lili .... nv lili .... nv lili .... سان .... ذكر تشانغ سان .... ذكر */في انتظار آلية الاستيقاظ
/**مؤشر ترابط آلية الاستيقاظ*يجب أن يكون الانتظار والاستيقاظ نفس القفل*/الفئة العامة ThreadDemo3 {علامات منطقية ثابتة = خطأ ؛ public static void main (string [] args) {class person {public string name ؛ سلسلة جنسية خاصة ؛ مجموعة void العامة (اسم السلسلة ، سلسلة الجنس) {this.name = name ؛ this.gender = الجنس ؛ } public void get () {system.out.println (this.name+"...."+this.gender) ؛ }} الشخص النهائي p = شخص جديد () ؛ مؤشر ترابط جديد (جديد RunNable () {public void run () {int x = 0 ؛ بينما (صحيح) {synchronized (p) {if (flags) try {p.wait () ؛} catch (interruptedException e) {// todo tuto catch block e.printstacktrace () ؛ } {p.set ("Lili" ، "NV") ؛ مؤشر ترابط جديد (جديد RunNable () {public void run () {بينما (صواب) {synchronized (p) {if (! flags) حاول {p.wait () ؛} catch (interruptedException e) {// todo auto catch block e.printstack () ؛} ؛ p.get () ؛ }).يبدأ()؛ }}آلية الإنتاج والاستهلاك واحد
الفئة العامة ThreadDemo4 {علامات منطقية ثابتة = خطأ ؛ public static void main (string [] args) {class goods {private string name ؛ خاص int num ؛ إنتاج الفراغ المتزامن العام (اسم السلسلة) {if (flags) حاول {wait () ؛ } catch (interruptedException e) {// todo catch catch e.printstacktrace () ؛ } this.name = name+"number:"+num ++ ؛ System.out.println ("المنتج ......"+this.name) ؛ أعلام = صواب ؛ إخطار () ؛ } استهلاك الفراغ المتزامن العام () {if (! flags) حاول {wait () ؛ } catch (interruptedException e) {// todo catch catch e.printstacktrace () ؛ } system.out.println ("الاستهلاك *****"+name) ؛ أعلام = خطأ ؛ إخطار () ؛ }} البضائع النهائية g = new goods () ؛ New Thread (new RunNable () {public void run () {بينما (true) {g.produce ("product") ؛}}}). start () ؛ مؤشر ترابط جديد (جديد RunNable () {public void run () {بينما (صحيح) {g.consume () ؛}}}). start () ؛ }}آلية الإنتاج والاستهلاك 2
الفئة العامة ThreadDemo4 {علامات منطقية ثابتة = خطأ ؛ public static void main (string [] args) {class goods {private string name ؛ خاص int num ؛ إنتاج الفراغ المتزامن العام (اسم السلسلة) {بينما (أعلام) حاول {wait () ؛ } catch (interruptedException e) {// todo catch catch e.printstacktrace () ؛ } this.name = name+"number:"+num ++ ؛ System.out.println (thread.currentThRead (). getName ()+"المنتج ..."+this.name) ؛ أعلام = صواب ؛ إخطار () ؛ } void synchronized steped () {بينما (! أعلام) حاول {wait () ؛ } catch (interruptedException e) {// todo catch catch e.printstacktrace () ؛ } system.out.println (thread.currentThRead (). getName ()+"استهلاك *******"+اسم) ؛ أعلام = خطأ ؛ إخطار () ؛ }} البضائع النهائية g = new goods () ؛ مؤشر ترابط جديد (جديد RunNable () {public void run () {بينما (صحيح) {g.produce ("المنتج") ؛}} ، "إنتاج (" منتج ") ؛}}} ،" المنتج (المنتج ") ؛}} ،" المنتج ("المنتج") ؛ } ، "المستهلك رقم 1"). start () ؛ مستهلك ******* رقم السلعة: 480500Producer رقم 1 المنتجة ... رقم السلعة: 48051Consumer رقم 2 المستهلك **** رقم السلعة: 48051PRODUCER No. 48053Consumer رقم 1 تم استهلاكه ******* رقم السلعة: 48053 تم إنتاج رقم 1 ... تم إنتاج رقم السلعة: 48054 Consumer رقم 2 تم استهلاكه ******* 48055*/ما سبق هو تجميع المعلومات متعددة الخيوط Java. سوف نستمر في إضافة المعرفة ذات الصلة في المستقبل. شكرا لك على دعمك لهذا الموقع!