English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
يقدم آلية توقف السطر طريقة لاستيقاظ السطر من حالة الانتظار، لتحاول إيقاف عملية السطر الحالية واستجابة الأوامر الجديدة. يمنح Java هذا الحرية للمطورين، يجب أن نستخدمه بشكل جيد.
اليوم نتحدث عن آلية توقف السطر في Java.
يقدم آلية توقف السطر طريقة لاستيقاظ السطر من حالة الانتظار، لتحاول إيقاف عملية السطر الحالية واستجابة الأوامر الجديدة. يمنح Java هذا الحرية للمطورين، يجب أن نستخدمه بشكل جيد.
استيقظ السطر من حالة الانتظار وتقوم بمعالجة التوقف التحكمي المناسب.
حاول إخبار السطر المستهدف: قم بإنهاء العمل الحالي واستجب للأمر الجديد.
مثال على الاستخدام الأول، انظر الكود التالي:
synchronized (lock) { try { while (!check()) { lock.wait(1000); } } e.printStackTrace(); } }
يستخدم هذا الكود آلية wait/notify التي توفرها Java، حيث يتم حجب السطر عند lock.wait()، هناك ثلاثة حالات تجعل السطر يعود إلى الحياة.
1. انتهاء الوقت المحدد 1000ms بشكل طبيعي، تنفيذ الجملة التالية.
2. تنفيذ السطر التالي من قبل السطر الآخر لاستيقاظ السطر المُنتظر
synchronized (lock) { lock.notifyAll(); // أو lock.notify(); }
سيتم تنفيذ الجملة التالية بشكل طبيعي.
3. طلب السطر الآخر لتقديم السطر المُنتظر إلى حالة التوقف
// للحصول على مرجع إلى السطر الذي ينتظر Thread a; a.interrupt();
السطر a المُتوقف سيقوم بإلقاء استثناء InterruptedException عند lock.wait();
في النهاية، يمكنك اعتبار أن object.wait() يقوم بما يلي:
boolean checkTimeout = timeout > 0; Thread current = Thread.currentThread(); lock.addWaiter(current); while (!current.isNotified()) { if (current.isInterrupted()) { current.clearInterrupted(); throw new InterruptedException(); } if (checkTimeout) { if (timeout == 0) break; timeout--; } }
هذا ليس دقيقًا تمامًا، لأن wait لا يستخدم هذا النوع من "التحقق بالدوران" للتحقق، ولكن منطق الحكم على راية القطع صحيح.
دعونا نبدأ بالتحقيق في عملية "إصدار القطع يدويًا" التي ذكرناها في المقطع السابق
// sun.nio.ch.Interruptible public interface Interruptible { void interrupt(Thread var1); } // java.lang.Thread private volatile Interruptible blocker; private final Object blockerLock = new Object(); public void interrupt() { if (this != Thread.currentThread()) checkAccess(); synchronized (blockerLock) { Interruptible b = blocker; if (b != null) { interrupt0(); b.interrupt(this); return; } } interrupt0(); } // فقط لتضبط راية القطع private native void interrupt0();
يمكن ملاحظة أن thread.interrupt() يتحقق من الصلاحيات أولاً، ثم يُدعى interrupt0() لتضبط راية القطع للشريط، وإذا كان لدى الشريط خاصية nio Interruptible، فإنه سيُدعى لها أيضًا.
لاحظ، interrupt0() هي فقط تضبط راية القطع للشريط.
عندما لا يكون الشريط غير معطل، وليس في منطقة object.wait()، thread.join()، Thread.sleep()، وما إلى ذلك من مناطق لا يتم التحكم فيها من قبل منطق البرنامج الجافا، فماذا سيحدث؟ الجواب هو لا شيء سيحدث، يمكن معرفة ما إذا تم قطع الشريط فقط من خلال التحقق من راية القطع بشكل نشط.
كيف يمكن التحقق؟Thread يقدم إثنين من الواجهات، Thread.interrupted() و thread.isInterrupted().
// java.lang.Thread public static boolean interrupted() { return currentThread().isInterrupted(true); } public boolean isInterrupted() { return isInterrupted(false); } private native boolean isInterrupted(boolean clearInterrupted);
يبدو أن كلاهما يعتمدان على isInterrupted(boolean)، والتي تعود إذا كانت النواة معطلة، وتبتعد علامة التحذير حسب الحاجة.
عندما سيتم إجراء حجب في دالة، يقوم مكتبة Java في مصدر الحجب بتعيين throws InterruptedException، ويطلب كتابة try catch لمعالجة التحذير.
عندما يحدث حجب للنواة، كما ذكرت في المقدمة، يقوم Java بفحص علامة التحذير، ويقوم بإزالتها أولاً، ثم يرفع InterruptedException.
// java.lang.Object public final void wait() throws InterruptedException { wait(0); } public final native void wait(long timeout) throws InterruptedException;
إذا استلمت نواة واحدة InterruptedException، واستمرت في تنفيذ كود سيؤدي إلى حجب، فإنها ستواصل الحجب مثل شخص لم يحدث شيء!
نكتب عادةً من فئات ثلاثة أنواع من الكود لمعالجة InterruptedException:
سيُنقل InterruptedException إلى الطبقة العليا لمعالجته.
public void foo() throws InterruptedException { synchronized (lock) { lock.wait(); } }
إعادة تعيين علامة الانقطاع عند مواجهة InterruptedException.
try { synchronized (lock) { lock.wait(); } } Thread.currentThread().interrupt(); //break; }
أولاً انتهي من العمل، ثم أعادة رمي InterruptedException.
public void bar() throws InterruptedException { InterruptedException ie = null; boolean done = false; while (!done) { synchronized (lock) { try { lock.wait(); } ie = e; continue; } } done = true; } if (ie != null) { throw ie; } }
إذا تجاهلت النواة أن تتجاهل علامة الانقطاع وـ InterruptedException، فإنها يمكن أن تعمل بشكل جيد. ولكن هذا يتعارض مع رؤيتنا الأصلية لتصميم المتواليات، حيث نأمل في أن تكون المتواليات تعمل بشكل متزامن وترتيبي لتحقيق وظيفة معينة، لذلك يجب على النواة الرد على الانقطاع. يترك Java هذا المجال للناسخين، وعلينا أن نستخدمه بشكل صحيح.
هذا هو كل محتوى التعريف بالآليات المتعلقة بالتدخل في نواة Java الذي قمنا بعرضه في هذه المرة، إذا كان لديك أي أسئلة، يمكنك مناقشتها في منطقة التعليقات في الأسفل، شكراً لدعم دليل الصراخ.
بيان: محتويات هذا المقال تم جمعها من الإنترنت، حقوق الطبع محفوظة للمالك الأصلي، المحتوى تم جمعه من قبل المستخدمين على الإنترنت، هذا الموقع لا يمتلك حقوق الملكية، لم يتم تعديل المحتوى بشكل يدوي، ولا يتحمل هذا الموقع أي مسؤولية قانونية مرتبطة. إذا لاحظت أي محتوى يخالف حقوق النسخ، فيرجى إرسال بريد إلكتروني إلى: notice#oldtoolbag.com (أثناء إرسال البريد الإلكتروني، يرجى استبدال '#' بـ '@') لتقديم الشكوى، وتقديم الدليل، وإذا تم التحقق من صحة الشكوى، سيتم حذف المحتوى المزعوم فوراً.