العديد من أسئلة مقابلة Java الأساسية تأتي من أطر عمل متعددة الخيوط ومجموعات. الخبرة العملية الممتازة ضرورية عند فهم مفهوم المواضيع الأساسية. تجمع هذه المقالة بعض الأسئلة النموذجية حول خيوط Java ، والتي غالباً ما يطرحها كبار المهندسين.
0. ما هو التزامن متعدد الخيوط في جافا؟
بموجب البرامج متعددة الخيوط ، يمكن للمزامنة التحكم في الوصول إلى الموارد المشتركة. إذا لم يكن هناك مزامنة ، عندما يقوم مؤشر ترابط Java بتعديل متغير مشترك ، فإن مؤشر ترابط آخر يستخدم أو تحديث نفس المتغير ، والذي يمكن أن يؤدي بسهولة إلى نتائج غير صحيحة في البرنامج.
1. اشرح عدة طرق لتنفيذ متعدد الخيوط؟
يمكن لخيط Java تطبيق الواجهة القابلة للتشغيل أو ورث فئة مؤشر الترابط لتنفيذها. عندما تخطط للوراثة عدة مرات ، فأنت تفضل تنفيذ Runnable.
2. ما هو الفرق بين thread.start () و thread.run ()؟
طريقة thread.start () (الأصلي) تبدأ الخيط ويدخل الحالة الجاهزة. عندما تخصص وحدة المعالجة المركزية الوقت للمعلومات ، تقوم جدولة JVM بتنفيذ طريقة Run ().
3. لماذا نحتاج إلى طرق التشغيل () وبدء ()؟ هل يمكننا فقط استخدام طريقة Run () لإكمال المهمة؟
نحتاج إلى طريقتين لـ Run () و START () لأن JVM ينشئ مؤشر ترابط منفصل يختلف عن نداء الأساليب العادية ، لذلك يتم هذا العمل بواسطة طريقة بدء مؤشر الترابط. يتم تنفيذ البدء بالطريقة المحلية ويجب أن تسمى بشكل واضح. ميزة أخرى لاستخدام هاتين الطريقتين هي أنه يمكن تشغيل أي كائن كخيط. طالما تم تنفيذ الواجهة القابلة للتشغيل ، فإن هذا يتجنب مشاكل الميراث المتعددة لـ Java الناجم عن وراثة فئة الخيط.
4. ما هي الفئة threadlocal وكيفية استخدامها؟
ThreadLocal هو متغير محلي على مستوى مؤشر الترابط ، وليس "مؤشر ترابط محلي". يوفر ThreadLocal نسخة مستقلة من المتغير لكل مؤشر ترابط يستخدم المتغير. لا يؤثر كل مؤشر ترابط على نسخة كائنات مؤشر ترابط أخرى عند تعديل النسخة (ملاحظة المترجم).
فيما يلي النقاط الرئيسية للمتغيرات المحلية:
يوفر المتغير المحلي (متغير ThreadLocal) مريح متغيرًا منفصلًا لكل مؤشر ترابط.
عادة ما تظهر مثيلات Threadlocal في فئة كحقول خاصة (ثابتة خاصة) ، والتي تستخدم لربط موضوع.
عندما يكون هناك عدة مؤشرات ترابط المصابين بالتوصيل ، يحافظ كل مؤشر ترابط على نسخة مستقلة من المتغيرات التي توفرها ThreadLocal.
يمكن رؤية الاستخدامات الشائعة الاستخدام في وضع DAO. عندما تكون فئة DAO عبارة عن فئة Singleton ، يتم الحفاظ على اتصال قاعدة البيانات بشكل مستقل بواسطة كل مؤشر ترابط ولا يؤثر على بعضها البعض. (Singleton استنادًا إلى الموضوع)
5. متى سيتم طرح invalidMonitorStateException ولماذا؟
عند استدعاء أي من الأساليب في WAIT ()/elefy ()/elefyall () ، إذا لم يحصل مؤشر الترابط الحالي على قفل الكائن ، فسيتم إلقاء استثناء من غير unalfalMonitorStateException (أي عندما لا ينفذ البرنامج أي كتلة المزامنة أو طريقة المزامنة للكائن ، فإنه لا يزال يحاول استدعاء الانتظار ()/الإشعارات ()/غير ذلك (). نظرًا لأن الاستثناء عبارة عن فئة فرعية من RunTimeexCpetion ، فلا يجب القبض على الاستثناء (على الرغم من أنه يمكنك التقاطه طالما تريد). باعتبارها runtimeexception ، لم يتم ذكر مثل هذه الاستثناءات في Wait () ، إخطار () ، توقيع طريقة الإخطار ().
6. ما هو الفرق بين النوم () ، تعليق () وانتظر ()؟
Thread.sleep () يجعل الخيط الحالي في حالة "غير قابلة للتشغيل" في الوقت المحدد. يحمل الموضوع دائمًا شاشة الكائن. على سبيل المثال ، إذا كان مؤشر ترابط حاليًا في كتلة التزامن أو طريقة التزامن ، لا يمكن لخيوط أخرى إدخال الكتلة أو الطريقة. إذا قام مؤشر ترابط آخر باستدعاء طريقة المقاطعة () ، فسوف يستيقظ هذا الخيط "النائم".
ملاحظة: Sleep () هي طريقة ثابتة. هذا يعني أنه صحيح فقط للمعلومات الحالية ، والخطأ الشائع هو استدعاء T.Sleep () ، (هنا T هو مؤشر ترابط يختلف عن مؤشر الترابط الحالي). حتى إذا تم تنفيذ T.Sleep () ، فإن الخيط الحالي سينام ، وليس الخيط T. T.SusPend () هي طريقة عفا عليها الزمن. يؤدي استخدام Copend () إلى دخول الخيط إلى حالة راكدة. سيحتفظ الخيط دائمًا بشاشة الكائن ، ومن المرجح أن يتسبب تعليق () في حدوث مشاكل في حالةدت.
Object.wait () يجعل الخيط الحالي يخرج من حالة "غير قابلة للعبادة". على عكس Sleep () ، الانتظار هو طريقة كائن بدلاً من مؤشر الترابط. عند استدعاء object.wait () ، يحتاج مؤشر الترابط أولاً إلى الحصول على قفل كائن هذا الكائن. يجب أن يحافظ مؤشر الترابط الحالي على كائن القفل متزامن وإضافة مؤشر الترابط الحالي إلى قائمة انتظار الانتظار. بعد ذلك ، يمكن لخيط آخر مزامنة قفل الكائن نفسه لاستدعاء كائن يشبه الانتظار ()/إخطار () بشكل أساسي Sleep ()/interrupt () ، باستثناء أن الأول يتطلب الحصول على قفل الكائن.
7. ماذا يحدث عند استخدام التزامن على الطرق الثابتة؟
عند مزامنة طريقة ثابتة ، سيتم الحصول على كائن "الفئة" للفئة. لذلك ، عندما يدخل مؤشر ترابط طريقة ثابتة متزامنة ، يكتسب مراقبة مؤشر الترابط قفل كائن الفئة نفسها ، ولا يمكن لخيوط أخرى إدخال أي طريقة مزامنة ثابتة لهذه الفئة. لا يشبه طريقة مثيل ، لأن مؤشرات الترابط المتعددة يمكنها الوصول إلى مثيلات مختلفة في وقت واحد متزامن.
8. عندما يتم تنفيذ طريقة المزامنة ، هل يمكن للمعلومات استدعاء طريقة المثيل غير المتزامن على الكائن؟
نعم ، يمكن دائمًا استدعاء طريقة غير متزامنة دون أي مشاكل. في الواقع ، لا تقوم Java بأي شيكات للطرق غير المتزامنة ، ويتم فحص كائنات القفل فقط في طرق التزامن أو كتل التعليمات البرمجية المتزامنة. إذا لم يتم الإعلان عن الطريقة على أنها متزامنة ، حتى لو كنت تستخدم البيانات المشتركة ، فستظل Java تسميها دون التحقق مما إذا كانت آمنة ، لذا كن حذرًا بشكل خاص في هذه الحالة. ما إذا كان يتم الإعلان عن الطريقة المتزامنة يعتمد على وصول القسم الحرج. إذا لم تصل الطريقة إلى القسم الحرج (الموارد المشتركة أو هياكل البيانات) ، فليس من الضروري إعلان متزامن.
فيما يلي مثال: لدى الفئة المشتركة طريقتين متزامنين method1 () و method1 () ، ومكتب الفئة myThread يستدعي هاتين الطريقتين في مؤشر ترابط مستقل.
الفئة العامة المشتركة {public synchronized void synchronizedmethod1 () {system.out.println ("synchronizedMethod1 sall") ؛ حاول {thread.sleep (1000) ؛ } catch (interruptedException e) {E.PrintStackTrace () ؛ } system.out.println ("synchronizedMethod1 done") ؛ } public void method1 () {system.out.println ("الطريقة 1 تسمى") ؛ حاول {thread.sleep (1000) ؛ } catch (interruptedException e) {E.PrintStackTrace () ؛ } system.out.println ("الطريقة 1 المنجز") ؛ }} الطبقة العامة myThread يمتد الموضوع {private int id = 0 ؛ شائع خاص ؛ MyThread العام (اسم السلسلة ، int no ، كائن مشترك) {super (name) ؛ مشترك = كائن ؛ معرف = لا ؛ } public void run () {system.out.println ("Running thread" + this.getName ()) ؛ حاول {if (id == 0) {common.synchronizedMethod1 () ؛ } آخر {common.method1 () ؛ }} catch (استثناء e) {E.PrintStackTrace () ؛ }} public static void main (string [] args) {common c = new Common () ؛ mythread t1 = new myThread ("mythread-1" ، 0 ، c) ؛ mythread t2 = new mythread ("mythread-2" ، 1 ، c) ؛ t1.start () ؛ t2.start () ؛ }}هنا إخراج البرنامج:
تشغيل ThreadMyThread-1
SynchronizedMethod1 دعا
تشغيل ThreadMyThread-2
الطريقة 1 تسمى
SynchronizedMethod1 القيام به
الطريقة 1 تم
تظهر النتائج أنه حتى إذا تم تنفيذ طريقة SynchronizedMethod1 () ، فسيتم استدعاء الطريقة 1 ().
9. هل يمكن لخيوط اثنين استدعاء طريقتين مختلفتين مثيل متزامن على كائن؟
لا ، لأن كائن ما قد تزامن طريقة المثيل ، يكتسب مؤشر الترابط قفل كائن الكائن. لذلك ، لا يمكن تنفيذ طرق التزامن الأخرى إلا بعد إصدار الطريقة بعد إصدار قفل الكائن. مثال الكود التالي واضح للغاية: لقد قامت الفئة المشتركة بمتزامنة method1 () وطرق SynchronizedMethod2 () ، ويدعو MyThread هاتين الطريقتين.
الفئة العامة المشتركة {public synchronized void synchronizedmethod1 () {system.out.println ("synchronizedMethod1 sall") ؛ حاول {thread.sleep (1000) ؛ } catch (interruptedException e) {E.PrintStackTrace () ؛ } system.out.println ("synchronizedMethod1 done") ؛ } synchronizedmethod2 () {system.out.println متزامن عام متزامن عام () حاول {thread.sleep (1000) ؛ } catch (interruptedException e) {E.PrintStackTrace () ؛ } system.out.println ("synchronizedMethod2 Done") ؛ }} الطبقة العامة myThread يمتد الموضوع {private int id = 0 ؛ شائع خاص ؛ MyThread العام (اسم السلسلة ، int no ، كائن مشترك) {super (name) ؛ مشترك = كائن ؛ معرف = لا ؛ } public void run () {system.out.println ("Running thread" + this.getName ()) ؛ حاول {if (id == 0) {common.synchronizedMethod1 () ؛ } آخر {common.synchronizedMethod2 () ؛ }} catch (استثناء e) {E.PrintStackTrace () ؛ }} public static void main (string [] args) {common c = new Common () ؛ mythread t1 = new myThread ("mythread-1" ، 0 ، c) ؛ mythread t2 = new mythread ("mythread-2" ، 1 ، c) ؛ t1.start () ؛ t2.start () ؛ }}10. ما هو adadlock
يعني Deadlock أنه يتم حظر خيوط اثنين أو أكثر بشكل غير محدود ، وينتظر المواضيع بعضها البعض للموارد المطلوبة. يمكن أن يحدث هذا عندما يحاول اثنين من المواضيع الحصول على أقفال لموارد أخرى ، ويتم انتظار كل مؤشر ترابط إلى أجل غير مسمى لإصدار أقفال الموارد الأخرى ما لم يتم إنهاء عملية المستخدم. بقدر ما يتعلق الأمر Javaapi ، قد تحدث مسدود الخيط في الموقف التالي.
11. ما هو الخيط الذي يتضور جوعا حتى الموت وما هو القفل الحي؟
على الرغم من أن الجوع في الخيوط وأقفال الحياة لا يعتبرون مشاكل شائعة مثل Deadlocks ، إلا أنها تشبه مواجهة مصممي البرمجة المتزامنة.
عندما يتم حظر جميع مؤشرات الترابط ، أو لا يمكن معالجتها لأن المورد المطلوب غير صالح ، فلا توجد مؤشرات ترابط غير محظورة لإتاحة المورد. قد تحدث الأقفال المباشرة في Javaapi في المواقف التالية:
الأسئلة هنا ليست مفصلة ، وآمل أن تكون مفيدة للجميع. إذا كان لديك أي أسئلة ، فيرجى ترك رسالة لي وسوف يرد المحرر على الجميع في الوقت المناسب. شكرا جزيلا لدعمكم لموقع wulin.com!