بدء الموضوع:
1. وصف الفرق بين Start () و Run ()
Start (): وظيفتها هي بدء مؤشر ترابط جديد ، وسيقوم مؤشر الترابط الجديد بتنفيذ طريقة Run () المقابلة. Start () لا يمكن استدعاؤها مرارًا وتكرارًا.
Run (): يمكن استدعاء Run () مرارًا وتكرارًا مثل أساليب الأعضاء العادية. إذا قمت بالاتصال بـ Run () بشكل منفصل ، فسيتم تنفيذ Run () في مؤشر الترابط الحالي ، ولن يتم بدء تشغيل الخيط الجديد!
فيما يلي رمز لشرح.
class myThread يمتد Thread {public void run () {...}} ؛ mythread myThread = new MyThread () ؛ يبدأ MyThread.start () مؤشر ترابط جديد ويقوم بتشغيل طريقة Run () في الخيط الجديد.
سيتم تشغيل MyThread.run () طريقة Run () مباشرة في الخيط الحالي ، ولن تبدأ مؤشر ترابط جديد للتشغيل ().
2. مثال على الفرق بين Start () و Run ()
أدناه ، أظهر الفرق بينهما مع مثال بسيط. رمز المصدر كما يلي:
. } public void run () {system.out.println (thread.currentThread (). getName ()+"is re rem") ؛ } ؛ System.out.println (thread.currentThRead (). getName ()+"Call MyThread.Run ()") ؛ mythread.run () ؛ System.out.println (thread.currentThRead (). getName ()+"Call MyThread.Start ()") ؛ mythread.start () ؛ }} نتائج التشغيل:
Main Call MyThread.run () Main هو RunningMain Call MyThread.Start () MyThread قيد التشغيل
وصف النتائج:
(1) thread.currentTherve (). getName () يستخدم للحصول على اسم "مؤشر الترابط الحالي". يشير مؤشر الترابط الحالي إلى مؤشر الترابط الذي من المقرر تنفيذه في وحدة المعالجة المركزية.
(2) mythread.run () يسمى في "Main Thread Main" ، وتشغيل طريقة Run () مباشرة على "Main Thread Main".
(3) سيبدأ MyThread.start () "Thread MyThread". بعد بدء "Thread mythread" ، سيتم استدعاء طريقة Run () ؛ في هذا الوقت ، يتم تشغيل طريقة Run () على "Thread MyThread".
المقاطعات والتقاطعات
1.
وظيفة المقاطعة () هي مقاطعة الخيط.
يسمح لهذا الموضوع بتقاطع نفسه ؛ عندما تستدعي مؤشرات الترابط الأخرى طريقة المقاطعة () لهذا الموضوع ، سيتم التحقق من الإذن من خلال CheckAccess (). هذا قد يرمي استثناء SecurityException.
إذا كان الخيط في حالة حظر: استدعاء الانتظار () ، فانتظر (طويل) أو انتظر (طويل ، int) من الخيط سيجعله في حالة انتظار (حظر) ، أو استدعاء الانضمام () ، الانضمام (طويل) ، الانضمام (طويل ، int) ، النوم (طويل) ، النوم (طويل ، int) من الخيط سيجعله أيضًا في حالة حجب. إذا استدعى الخيط طريقة المقاطعة () عند حظره ، فسيتم مسح "حالة المقاطعة" وسيتم استلام مقاطع. على سبيل المثال ، يدخل مؤشر ترابط حالة حظر من خلال WAIT () ، ويتم مقاطعة الخيط بواسطة Interrupt () ؛ سيقوم استدعاء Interrupt () على الفور بتعيين علامة مقاطعة مؤشر الترابط على "True" ، ولكن نظرًا لأن الخيط في حالة حظر ، سيتم مسح "علامة المقاطعة" على الفور إلى "False" ، وسيتم إنشاء مقاطع.
إذا تم حظر الخيط في محدد محدد ، عنده عند مقاطعته بواسطة Interrupt () ؛ تم تعيين علامة مقاطعة مؤشر الترابط على TRUE وسيتم إرجاعها فورًا من عملية التحديد.
إذا لم يكن ينتمي إلى الموقف المذكور أعلاه ، فحينئذٍ عند مقاطعة الخيط من خلال Interrupt () ، سيتم ضبط علامة المقاطعة على "True".
مقاطعة "الخيط المنتهي" لن يسبب أي عملية.
2. إنهاء الموضوع
يوصى باستخدام أساليب STOP () ومعلق () في مؤشر الترابط بسبب انعدام الأمن المتأصل!
بعد ذلك ، سأناقش أولاً طريقة إنهاء مؤشرات الترابط في "حظر الحالة" و "حالة التشغيل" على التوالي ، ثم تلخيص طريقة عامة.
1. إنهاء الخيط في "حالة الحظر"
عادةً ما ننهي موضوعًا في "حالة حظر" عن طريق "مقاطعة".
عندما يدخل الخيط إلى حالة حظر بسبب تسمى Sleep () ، وانتظر () ، والانضمام () وطرق أخرى ؛ إذا تم استدعاء المقاطعة () من مؤشر الترابط في هذا الوقت ، يتم تعيين علامة المقاطعة للخيط على TRUE. نظرًا لأنه في حالة حظر ، سيتم مسح علامة المقاطعة ويتم إنشاء استثناء مقاطع. يمكن وضع InterruptedException حتى يكون مناسبًا إنهاء الخيط ، في النموذج على النحو التالي:
Overridepublic void run () {try {بينما (صحيح) {// قم بتنفيذ المهمة ...}} catch (interruptedException ie) {// بسبب استثناء interruptedException ، قم بالخروج من الحلقة (True) وترسل سلسلة الرسائل! }} ملاحظة: عندما يتم تنفيذ المهمة بشكل مستمر في حين (صواب) ، عندما يكون الخيط في حالة حظر ، فإن الدعوة إلى المقاطعة () من مؤشر الترابط تنشئ مقاطعة EnterruptedException. الالتقاط المتقطع خارج بينما (صحيح) ، وبالتالي الخروج من حلقة (حقيقية)!
ملاحظة: يتم وضع التقاط من InterruptedException عادة خارج الجسم (الحقيقي) ، بحيث تخرج الحلقة (الحقيقية) عند إنشاء استثناء. خلاف ذلك ، إذا كان InterruptedException هو ضمن الجسم (الحقيقي) ، فإن الإضافة الإضافية والخروج مطلوبة. النموذج كما يلي:
Overridepublic void Run () {بينما (صحيح) {try {// تنفيذ المهمة ...} catch (interruptedException ie) {// interruptedException في الجسم (true). // عندما يقوم الخيط بإنشاء استثناء من المقاطعات ، في حين أن (صحيح) يمكن أن يستمر في التشغيل! تحتاج إلى الخروج يدويًا ؛ }}} ملاحظة: يتم اكتشاف استثناء InterruptedException داخل Whle (صحيح). عندما يتم إنشاء استثناء من المقاطعات ، لا يتم التعامل معه عن طريق الصيد ولا يزال في جسم الحلقة (الحقيقي) ؛ للخروج من جسم الحلقة (الحقيقي) ، يجب إجراء عملية إضافية للخروج من الوقت (الحقيقي).
2. إنهاء الخيط في "حالة الجري"
عادةً ما ننهي موضوعًا في "حالة الجري" بواسطة "علامات". من بينها ، يشمل "العلم المقاطعة" و "إضافة علامة إضافية".
(1) إنهاء الخيط من خلال "العلم المقاطعة".
النموذج كما يلي:
Overridepublic void Run () {بينما (! isInterrupted ()) {// تنفيذ المهمة ...}} الوصف: IsInterrupted () يحدد ما إذا كانت علامة مقاطعة الخيط صحيحة. عندما يكون الخيط في حالة الجري ونحتاج إلى إنهاءه ؛ يمكن استدعاء طريقة مقاطعة مؤشر الترابط () ، ويتم وضع علامة على علامة مقاطعة مؤشر الترابط ، أي isInterrupted () ستعود صحيحًا. في هذه المرحلة ، سيتم الخروج من الحلقة.
ملاحظة: لا ينهي Interrupt () مؤشرات الترابط في "حالة الجري"! يقوم بتعيين علامة مقاطعة الموضوع على TRUE.
(2) تمرير "إضافة علامات إضافية".
النموذج كما يلي:
علامة منطقية متطايرة خاصة = صواب ؛ محمي باطل stopTask () {flag = false ؛}@overridepublic run () {بينما (flag) {// تنفيذ المهمة ...}} الوصف: هناك علامة علامة في مؤشر الترابط ، وقيمتها الافتراضية صحيحة ؛ ونحن نقدم stopTask () لتعيين علامة العلم. عندما نحتاج إلى إنهاء مؤشر الترابط ، يمكن أن يتسبب استدعاء طريقة stopTask () في مؤشر الترابط في خروج مؤشر الترابط من الحلقة.
ملاحظة: يتم تعريف العلامة على أنها النوع المتقلبة لضمان رؤية العلم. وهذا هو ، بعد تعديل المواضيع الأخرى العلامة من خلال stopTask () ، يمكن لهذا الموضوع رؤية قيمة العلامة المعدلة.
شامل أساليب إنهاء المواضيع في "حالة حظر" و "حالة الجري" ، كلما كانت مؤشرات الترابط الأكثر شيوعًا هي كما يلي:
Overridepublic void Run () {try {// 1. isInterrupted () يضمن إنهاء مؤشر الترابط طالما تم وضع علامة على المقاطعة. بينما (! isInterrupted ()) {// تنفيذ المهمة ...}} catch (interruptedException ie) {// 2. استثناء InterruptedException يضمن أنه عند حدوث استثناء مقاطع ، يتم إنهاء مؤشر الترابط. }} 3. مثال لإنهاء الموضوع
غالبًا ما يتم استخدام المقاطعة () لإنهاء موضوع "حالة الحظر". الرجوع إلى المثال التالي:
// DEMO1.JAVA ، فئة الكود المصدري ، MyTherd يمتد Thread {public mythread (اسم السلسلة) {super (name) ؛ } Override public void run () {try {int i = 0 ؛ بينما (! isInterrupted ()) {thread.sleep (100) ؛ // Sleep 100ms i ++ ؛ system.out.println (thread.currentThRead (). getName ()+"("+this.getState ()+") loop"+i) ؛ }} catch (interruptedException e) {system.out.println (thread.currentThread (). getName ()+"("+this.getState ()+") catch interruptedException.") ؛ }}} الفئة العامة demo1 {public static void main (string [] args) {try {thread t1 = new MyThread ("t1") ؛ // قم بإنشاء "Thread T1" system.out.println (t1.getName ()+"("+t1.getState ()+") جديد.") ؛ t1.start () ؛ // ابدأ "thread t1" system.out.println (t1.getName ()+"("+t1.getState ()+") تم البدء.") ؛ // ينام الخيط الرئيسي لـ 300 مللي ثانية ، ثم يرسل الخيط الرئيسي تعليمات "مقاطعة" إلى T1. thread.sleep (300) ؛ T1.Interrupt () ؛ System.out.println (t1.getName ()+"("+t1.getState ()+") متقطع.") ؛ // ينام الخيط الرئيسي لـ 300 مللي ثانية ، ثم يتحقق من حالة T1. thread.sleep (300) ؛ System.out.println (t1.getName ()+"("+t1.getState ()+") متقطع الآن.") ؛ } catch (interruptedException e) {E.PrintStackTrace () ؛ }}} نتائج التشغيل:
تم تشغيل T1 (جديد) جديد.
وصف النتائج:
(1) يقوم مؤشر الترابط الرئيسي بإنشاء موضوع T1 من خلال myThread جديد ("T1") ، ثم يبدأ الخيط T1 من خلال T1.start ().
(2) بعد بدء تشغيل T1 ، سيتم فحص علامة المقاطعة بشكل مستمر. إذا كانت علامة المقاطعة "خاطئة" ، فسوف ينام مقابل 100 مللي ثانية.
(3) بعد نوم T1 ، سوف يتحول إلى الخيط الرئيسي الرئيسي ؛ عندما يتم تشغيل الخيط الرئيسي مرة أخرى ، سيتم تنفيذ T1.Interrupt () لمقاطعة الخيط T1. بعد أن يتلقى T1 تعليمات المقاطعة ، سيتم ضبط علامة المقاطعة لـ T1 على "False" وسيتم إلقاء مقاطع. في طريقة Run () لـ T1 ، إنه استثناء تم صيده خارج جسم الحلقة أثناء ذلك ؛ لذلك تم إنهاء الحلقة.
لقد قمنا بتعديل صغير للنتيجة أعلاه ونقلنا كتلة الكود التي اشتعلت استثناء المقاطعات في طريقة Run () إلى جسم الحلقة.
. } Override public void run () {int i = 0 ؛ بينما (! isInterrupted ()) {try {thread.sleep (100) ؛ // sleep for 100ms} catch (interruptedException ie) {system.out.println (thread.currentThRead (). getName ()+"("+this.getState ()+") catch interruptedException.") ؛ } i ++ ؛ system.out.println (thread.currentThRead (). getName ()+"("+this.getState ()+") loop"+i) ؛ }}} الفئة العامة demo2 {public static void main (string [] args) {try {thread t1 = new MyThread ("t1") ؛ // قم بإنشاء "Thread T1" system.out.println (t1.getName ()+"("+t1.getState ()+") جديد.") ؛ t1.start () ؛ // ابدأ "thread t1" system.out.println (t1.getName ()+"("+t1.getState ()+") تم البدء.") ؛ // ينام الخيط الرئيسي لـ 300 مللي ثانية ، ثم يرسل الخيط الرئيسي تعليمات "مقاطعة" إلى T1. thread.sleep (300) ؛ T1.Interrupt () ؛ System.out.println (t1.getName ()+"("+t1.getState ()+") متقطع.") ؛ // ينام الخيط الرئيسي لـ 300 مللي ثانية ، ثم يتحقق من حالة T1. thread.sleep (300) ؛ System.out.println (t1.getName ()+"("+t1.getState ()+") متقطع الآن.") ؛ } catch (interruptedException e) {E.PrintStackTrace () ؛ }}} نتائج التشغيل:
تم بدء تشغيل T1 (جديد) جديد. (Runnable) حلقة 6T1 (RunNable) حلقة 7T1 (Runnable) حلقة 8T1 (RunNable) 9 ...
وصف النتائج:
دخل البرنامج حلقة ميتة!
لماذا هذا يحدث؟ وذلك لأن T1 قد انقطع عن طريق Interrupt () عندما يكون "ينتظر (حظر) حالة". في هذا الوقت ، يتم مسح علامة المقاطعة [التي تمت مقاطعة () سيعود كاذبة] ، ويتم إلقاء استثناء من المقاطعات [يتم اكتشاف هذا الاستثناء في جسم الحلقة]. لذلك ، سوف يدخل T1 بشكل طبيعي في دورة مفرغة.
لحل هذه المشكلة ، نحتاج إلى معالجة إضافية للخروج من الحلقة أثناء التقاط الاستثناء. على سبيل المثال ، يمكن لإضافة Break أو العودة إلى catch (InterruptedException) حل المشكلة.
فيما يلي مثال على مؤشر ترابط ينهي "حالة الحالة" عن طريق "إضافة علامات إضافية":
. public void stopTask () {flag = false ؛ } myThread (اسم السلسلة) {super (name) ؛ } Override public void run () {synchronized (this) {try {int i = 0 ؛ بينما (العلم) {thread.sleep (100) ؛ // Sleep 100ms i ++ ؛ system.out.println (thread.currentThRead (). getName ()+"("+this.getState ()+") loop"+i) ؛ }} catch (interruptedException ie) {system.out.println (thread.currentThRead (). getName ()+"("+this.getState ()+") catch interruptedException.") ؛ }}}} الفئة العامة demo3 {public static void main (string [] args) {try {mythread t1 = new MyThread ("t1") ؛ // قم بإنشاء "Thread T1" system.out.println (t1.getName ())+"("+t1.getState ()+") جديد.") ؛ t1.start () ؛ // ابدأ "thread t1" system.out.println (t1.getName ()+"("+t1.getState ()+") تم البدء.") ؛ // ينام الخيط الرئيسي لـ 300 مللي ثانية ، ثم يرسل الخيط الرئيسي تعليمات "مقاطعة" إلى T1. thread.sleep (300) ؛ T1.StopTask () ؛ System.out.println (t1.getName ()+"("+t1.getState ()+") متقطع.") ؛ // ينام الخيط الرئيسي لـ 300 مللي ثانية ، ثم يتحقق من حالة T1. thread.sleep (300) ؛ System.out.println (t1.getName ()+"("+t1.getState ()+") متقطع الآن.") ؛ } catch (interruptedException e) {E.PrintStackTrace () ؛ }}} نتائج التشغيل:
تم بدء تشغيل T1 (جديد) جديد.