سؤال

أنا أستخدم نهج Spinlock التالي:

while(!hasPerformedAction()){
    //wait for the user to perform the action
    //can add timer here too
}

setHasPerformedAction(false);

return getActionPerfomed();

هذا ينتظر بشكل أساسي أن يقوم المستخدم بإجراء ما ثم يعيده. حاليًا يطلب شيء ما إجابة من المستخدم قبل المتابعة ، ولهذا السبب أنتظر حتى يتم استلام الإدخال. ومع ذلك ، كنت أتساءل عما إذا كان هذا غير فعال ، وإذا كنا ننتظر لفترة من الوقت (أي <= 30 ثانية) ، فسيؤدي إلى إبطاء الكمبيوتر الذي يقوم بتشغيل هذا التطبيق. هل هناك أي بدائل أخرى تستخدم هذا النهج ، أي أقفال ، وسائل الإشارات إذا كان الأمر كذلك ، فما هو بناء الجملة؟

شكرًا،

علي

هل كانت مفيدة؟

المحلول

في الواقع ، ليس هذا غير فعال فحسب ، بل إنه ليس مضمونًا حتى العمل ، نظرًا لعدم وجود ميزة "يحدث قبل" في الكود الذي تعرضه. لخلق يحدث قبل الحافة تحتاج إلى القيام بواحد من:

  1. الوصول إلى متغير متطاير
  2. تزامن مع مورد مشترك
  3. استخدام قفل utils المتزامن.

كما ذكر في تعليق آخر ، أسهل الحل ، هو ببساطة التأكد من أن علمك هو متغير متقلبة ، وببساطة رمي نوم قصير في حلقتك.

ومع ذلك ، فإن أفضل ما يجب فعله هو مزامنة/الانتظار/الإخطار بمتغير مشترك.

الطرق التي تحتاج إلى قراءتها انتظر و إخطار. للحصول على وصف أفضل حول كيفية استخدام هذه ، اقرأ هذه المقالة. يظهر مقتطف رمز مثال أدناه ؛

الموضوع 1

Object shared = new Object();
startThread2(shared);
synchronized (shared) {
  while (taskNotDone())
    shared.wait();
}

الموضوع 2

// shared was saved at the start of the thread
// do some stuff
markTaskAsDone();
synchronized (shared) {
  shared.notify();
}

نصائح أخرى

ما كتبته يسمى Looping مشغول ، وهو ما يجب عليك فعله أبدًا.

قد ترغب في الاستمرار في القيام بذلك ، ولكن على الأقل تنام قليلاً حتى لا تكون مشغولاً ، والتي لا تزال رائعة:

while( !hasPerformedAction() ) {
    (sleep a bit here)
}

هناك طريقة أخرى للقيام بذلك من شأنها أن تفعيل إجراءات المستخدم في قائمة انتظار الحظر: ثم يمكنك ببساطة استخدام ملف Queue.take وسيهتم تطبيق قائمة الانتظار بالقضية بالنسبة لك.

وستكون هناك طريقة أخرى لاستخدام رد الاتصال لإخطارها بإجراءات المستخدم.

دروس Java لديها درس جيد حول التزامن في جافا:

http://java.sun.com/docs/books/tutorial/essential/concurrency/

إذا كنت ستقوم بتعديل واجهة المستخدم من موضوع آخر ، فستحتاج إلى تذكر أن تفعل:

SwingUtils.invokeLater(actionToInvoke);

هناك واجهة المستخدم الرسومية في علاماتك ، لذلك سأفترض أن الإجراء يتم في واجهة المستخدم الرسومية.

الطريقة "الموصى بها" للقيام بهذا النوع من الأشياء هي أن يضع الخيط الرئيسي نفسه في النوم (ربما باستخدام wait()) ولإجراء واجهة المستخدم الرسومية إلى notify() عاد إلى اليقظة بمجرد تنفيذ الإجراء.

هناك بعض الفصول لذلك في java.util.concurrent.locks. ألق نظرة على الفصل LockSupport

تحيات مايك

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top