ملخص وتأملات في برمجة جافا المتزامنة

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

لماذا التزامن

التزامن هو في الواقع استراتيجية فصل، فإنه يساعد ما (الهدف) يتعين علينا القيام به وعندما نفعل ذلك (الوقت) فصل. يمكن القيام بذلك بشكل ملحوظ تحسين الإنتاجية من التطبيق (لمزيد من الوقت جدولة CPU) وهيكل (عدد وافر من أجزاء من برنامج العمل معا). لم تطوير جافا ويب الناس يعرفون، برنامج بريمج جافا ويب في نسخة واحدة من وضع التشغيل باستخدام خاصية تعدد بدعم من الحاويات بريمج، حاوية بريمج كما تتعامل مع قضايا التزامن.

سوء الفهم والحلول الإيجابية

الأكثر شيوعا من هذه هي المتزامنة سوء الفهم البرمجة التالية:

(يمكن أن تحسن بشكل كبير من أداء برنامج المتزامنة في وحدة المعالجة المركزية لديها الكثير من وقت الفراغ، ولكن عددا أكبر من المواضيع عند التبديل بين المواضيع جدول المتكرر من شأنه أن يعطي تدهور أداء النظام) متزامنة دائما تحسين الأداء -

- البرامج المتزامنة الكتابة دون تعديل التصميم الأصلي (غرض وتوقيت فصل تميل إلى أن يكون لها تأثير كبير على تكوين النظام)

- لا تركز على مشكلات التوافق عند استخدام الإنترنت أو حاوية EJB (حاوية علم فقط ما يجب القيام به من أجل الاستفادة بشكل أفضل من الحاوية)

البيان التالي هو فهم الهدف المتزامنة:

- كتابة البرنامج المتزامنة سيضيف مقدار حمل إضافي على رمز

- التزامن الصحيح معقد جدا، حتى بالنسبة للسؤال بسيط جدا

- بالتزامن يصعب استنساخها لأنه لم يتم العثور على العيوب بسهولة

- غالبا ما تحتاج استراتيجيات التصميم المتزامنة إلى تعديل جذري

مبادئ البرمجة المتزامنة والتقنيات

مبدأ المسؤولية احد

منفصل كود ذات الصلة المتزامنة ورمز آخر (رمز المتزامنة ذات الصلة ديه تنميته وتعديل وضبط دورة حياة).

تحديد نطاق البيانات

اثنين من المواضيع قد تتداخل مع بعضها البعض عند تعديل نفس المجال الكائن المشترك، مما يؤدي إلى سلوك غير متوقع، حل واحد هو بناء منطقة حرجة، ولكن يجب الحد من عدد من المجالات الحيوية.

استخدام نسخ من البيانات

نسخ من البيانات هو وسيلة جيدة لتبادل البيانات وتتجنب نسخ الكائن للخروج من الطريق فقط في العلاج للقراءة فقط. جافا حزمة java.util.concurrent 5 لإضافة فئة تسمى CopyOnWriteArrayList، وهو نوع فرعي من واجهة قائمة، لذلك قد اعتقد انه من نسخة موضوع الآمن للArrayList، فإنه يستخدم نسخة عند الكتابة وسيلة لإنشاء نسخة من البيانات تعمل لتجنب مشكلة الوصول المتزامن إلى البيانات المشتركة تشغيلها.

وينبغي أن يكون موضوع مستقل قدر الإمكان

كاتب الموضوع موجودة في عالمهم الخاص، لا تبادل البيانات مع المواضيع الأخرى. وقد كان للمطورين جافا ويب تجربة الناس يعرفون، بريمج هو مثيل واحد من وسيلة مؤشرات العمل، ويتم تمرير كل من طلبات البيانات ذات الصلة عن طريق أسلوب خدمة المعلمة بريمج فرعية (أو doGet أو doPost طريقة) أ. طالما الاستخدامات كود بريمج فقط المتغيرات المحلية، بريمج لن يسبب مشاكل التزامن. تحكم springMVC هو أن تفعل ذلك، يتم الحصول على كائن من يتم تمرير الطلب إلى معلمات الأسلوب وليس كعضو في الصف، فمن الواضح أن الدعامات ممارسة 2 على العكس من ذلك، وذلك تحكم الطبقة الدعامات 2 عمل هي كل طلب يتوافق مع مثال واحد.

5 جافا البرمجة المتزامنة قبل

ويستند جافا طراز مؤشر الترابط على جدولة موضوع وقائية، وهذا يعني:

  • جميع المواضيع في الكائنات نفسها عملية يمكن مشاركتها بسهولة.
  • أي موضوع يمكن الرجوع هذه الكائنات يمكن تعديل هذه الكائنات.
  • لحماية البيانات، والأشياء يمكن أن يكون مؤمنا.

جافا القائمة بين خيوط المتزامنة وأقفال أسفل أيضا، واستخدام الأقفال وغالبا ما تكون الشر ذاته، لأنه يعادل جميعا قد تصبح متزامنة في قائمة الانتظار.

في السابق جافا 5، ويمكن استخدامها لتنفيذ متزامنة ميزة قفل الكلمات الرئيسية، والتي يمكن استخدامها في كتل رمز والأساليب التي يجب أن موضوع الحصول على قفل المناسب قبل تنفيذ كتلة التعليمات البرمجية بأكمله أو الأسلوب. لأسلوب غير ثابت (عضو الأسلوب) فئة، يعني ذلك أن يكتسب قفل إلى مثيل كائن، أساليب ثابتة (أساليب الفئة) فئة، الكائن الفئة للحصول على قفل فئة لكتلة التعليمات البرمجية التزامن، برنامج ويمكن لأعضاء يحدد ان كنت ترغب في الحصول على جسم القفل.

أم تزامن كتلة طريقة تزامن الرمز، يمكن أن مؤشر واحد فقط يدخل، إذا المواضيع الأخرى التي تحاول إدخال (إما نفس أو مختلفة كتل تزامن كتلة مزامنة)، وJVM شنق منهم (في القفل إلى التجمع، وما إلى ذلك) . وهذا ما يسمى هيكل المنطقة الحرجة (مقطع حرج) نظرية المتزامنة. هنا يمكننا تحقيق وظائف تزامن وقفل للجافا باستخدام متزامنة لتقديم موجز:

  • يمكن قفل الأشياء، وأنواع البيانات بدائية لا يمكن تأمين
  • مجموعة من كائن واحد في كائن غير مؤمن مؤمنة
  • يمكن اعتبار طريقة تزامن لاحتواء طريقة بأكمله متزامنة (هذا) {...} كتلة التعليمات البرمجية
  • ثابت متزامنة طريقة سوف تغلق الكائن فئتها
  • الطبقات الداخلية مستقلة عن الطبقة تزامن الخارجية
  • معدل متزامنة ليست جزءا من توقيع الأسلوب، لذلك لا يمكن أن تظهر في إعلان أسلوب واجهة
  • ، فإنها ما زالت قائمة يمكن تشغيل الأسلوب غير متزامن لا يهتمون حالة القفل في طريقة تزامن وقت التشغيل
  • تتم مزامنة أقفال لتحقيق قفل عودة الدخول.

داخل JVM، من أجل تحسين كفاءة أثناء تشغيل كل موضوع سوف يكون لديك نسخة مخبأة من البيانات التي يتم معالجة، عندما نستخدمها synchronzied المزامنة عند التزامن هو الكائنات المؤمنة حقا في المواضيع المختلفة للكتل الذاكرة (نسخ من بقايا البيانات المتزامنة والذاكرة الرئيسية، والآن أعرف لماذا استخدام مصطلح تزامن ذلك)، يعني ببساطة أن الكتل التزامن أو طريقة تزامن بعد تنفيذ أية تغييرات على الكائنات المؤمنة التي تريدها لتحرير القفل كتب قبل العودة إلى الذاكرة الرئيسية، وبعد دخول كتلة متزامنة للحصول على القفل، للقراءة وجوه البيانات المؤمنة الخروج من الذاكرة الرئيسية، ونسخة من البيانات تتم مزامنة موضوع عقد خصلة من وجهة نظر معينة من الذاكرة الرئيسية والبيانات.

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

  • قيمة المتغير دائما قبل الاستخدام ثم قراءة من الذاكرة الرئيسية.
  • تعديل دائما قيم المتغيرات بعد الانتهاء يعود مكتوبة إلى الذاكرة الرئيسية.

استخدم الكلمة الأساسية المتقلبة يمكن أن تمنع مترجم الأمثل افتراض غير صحيح أن في بيئة مؤشرات (قد مترجم متغير لا تتغير في قيمة موضوع ثابت الأمثل ل)، ولكن لا تعتمد على الوضع الراهن (قراءة معدلة فقط يجب أن تعلن قيمة عندما تؤخذ) متغير فقط كمتغيرات المضطربة.

نفس النمط هو أيضا التصميم الذي يمكن اعتبار البرمجة المتزامنة. دع حالة الكائن هو ثابت، إذا كانت الدولة لتعديل الكائن الأمل، فإنه سيتم إنشاء نسخة من نسخة خطية من وجوه والتغيير دون تغيير الكائن الأصلي، وبالتالي فإن حالة غير متناسقة لن يحدث، وبالتالي فإن الهدف من ذلك هو دون تغيير موضوع آمن. جافا، ونحن نستخدم تردد عال جدا من الفئة سلسلة على استخدام تصميم مثل هذا. إذا كنت وضع ثابت غير مألوف، يمكن أن تقرأ الفصل 34 الإعاقة يان هونغبو "جافا ونموذج"، وهو الكتاب. هنا يمكنك أيضا نقدر أهمية الكلمة النهائية.

5 جافا البرمجة المتزامنة

بغض النظر عن ما هو الاتجاه نحو المستقبل للتنمية جافا أو يهلك، جافا 5 جافا هو بالتأكيد في تاريخ إصدار مهم جدا، وهذا الإصدار يقدم مجموعة متنوعة من ميزات اللغة، نحن لسنا مناقشتها هنا (المهتمين يمكن قراءة مقالتي أخرى "20 سنة الأولى من جاوة: إصدار جافا كما يبدو من تطور لتطور تقنيات البرمجة")، ولكن علينا أن أشكر المقدمة دوغ ليا له معلما حزمة java.util.concurrent تحفة في جاوة 5، يبدو لجعل جافا البرمجة المتزامنة مع المزيد من الخيارات وطرق أفضل للعمل. وتشمل روائع دوغ ليا في ما يلي:

  • الخيط آمنة أفضل الحاويات
  • تجمع الموضوع والأدوات ذات الصلة
  • الحل الاختياري عرقلة غير
  • أقفال عرض الآلية والإشارات

نحن هنا يقرأ هذه الأشياء.

- أتوم

حزمة Java.util.concurrent في جاوة 5 الذري تحت حزمة الفرعية، التي هناك عدة فئات بداية الذرية، على سبيل المثال AtomicInteger وAtomicLong. وهم يستغلون خصائص المعالجات الحديثة، قد يكون عدم عرقلة اكتمال بطريقة عملية الذرية، كما يلي رمز:

/ ** ID تسلسل مولد * / الطبقة العامة IdGenerator { النهائي الخاص AtomicLong SequenceNumber و= AtomicLong جديد (0)؛ الجمهور طويلا المقبل () { العودة sequenceNumber.getAndIncrement ()؛ } }

قفل الشاشة

لديك على الأسئلة التالية على أساس الكلمة آلية قفل متزامنة:

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

تم إعادة هيكلة جافا آلية 5 قفل لتقديم عرض القفل، حتى تتمكن من رفع آلية تأمين في المجالات التالية:

  • يمكنك إضافة أنواع مختلفة من الأقفال، وقراءة الأقفال والكتابة الأقفال على سبيل المثال
  • يمكن أن يكون مؤمنا في نهج واحد، مقفلة طريقة أخرى
  • يمكنك استخدام الطريقة tryLock في محاولة للحصول على قفل، وإذا كان القفل لا يمكن أن تنتظر، وإرجاع التسجيل أو تفعل شيئا آخر، وبطبيعة الحال، يمكنك التخلي عن العملية بعد مهلة

عرض أقفال يتم تنفيذ واجهات java.util.concurrent.Lock، هناك فئات تنفيذ اثنين:

  • ReentrantLock - قليلا أكثر مرونة من تأمين عودة الدخول متزامنة
  • ReentrantReadWriteLock - قرأت الكثير في وقت قصير جدا أداء الكتابة أفضل من تأمين عودة الدخول

لمعرفة كيفية استخدام قفل الشاشة، ويمكن الرجوع إلى سلسلة مقابلة جافا "مجموعة جافا أسئلة المقابلة 51-70" في عنوان المادة 60 من التعليمات البرمجية. نشير فقط أن نتذكر، استدعاء الأسلوب فتح هي الأقدر على فتح أخيرا الكتلة، لأنه هنا هو أفضل مكان للافراج عن الموارد الخارجية، وبطبيعة الحال، فإن أفضل مكان للافراج عن قفل، لأنه لا يوجد تشوهات مسألة قد تكون طبيعية لتأمين الافراج عن سقوط فرص المواضيع الأخرى لتشغيل.

CountDownLatch

CountDownLatch هو وضع متزامن بسيطة، والتي تسمح للموضوع يمكن أن تنتظر واحد أو أكثر المواضيع لاستكمال عملهم وذلك لتجنب مشاكل الوصول المتزامن إلى الموارد الحيوية الذي تسببت فيه. شخص ما الاقتراض التالية هو آخر قطعة من التعليمات البرمجية (لم بعض إعادة عرض عليه) لإظهار كيفية عمل CountDownLatch.

استيراد java.util.concurrent.CountDownLatch. / ** * فئة العمال *Author لوه هاو * * / فئة العمال { اسم سلسلة الخاص؛ اسم // workDuration طويلة الخاص؛ // مدة / ** * منشئ * / الجمهور العلمي (اسم سلسلة طويلة workDuration) { this.name = الاسم؛ this.workDuration = workDuration. } / ** * الانتهاء من العمل * / doWork باطلة العامة () { System.out.println (اسم + "يبدأ في العمل ...")؛ محاولة { إجراء // العمل لبعض الوقت المحاكاة نائمة، Thread.sleep (workDuration) } صيد (InterruptedException السابق) { ex.printStackTrace ()؛ } System.out.println (اسم + "قد انتهى من العمل ...")؛ } } / ** * موضوع الاختبار *Author لوه هاو * * / الطبقة WorkerTestThread الأدوات Runnable { عامل عامل الخاص؛ خاصة CountDownLatch cdLatch. الجمهور WorkerTestThread (عامل العلمي، CountDownLatch cdLatch) { this.worker = عامل. this.cdLatch = cdLatch. } Override المدى باطلة العامة () { worker.doWork ()؛ // تمكين العاملين من العمل cdLatch.countDown ()؛ // بعد الانتهاء من العد التنازلي عدد ناقص 1 } } الطبقة CountDownLatchTest { ساكنة الخاص نهائي الباحث MAX_WORK_DURATION = 5000؛ // الحد الأقصى لساعات العمل ساكنة الخاص نهائي الباحث MIN_WORK_DURATION = 1000؛ // الحد الأدنى وقت العمل // توليد ساعات العمل عشوائية ساكنة الخاص getRandomWorkDuration طويل (دقيقة طويلة، الحد الأقصى لفترة طويلة) { عودة (طويل) (Math.random () * (ماكس - دقيقة) + دقيقة). } ساكنة العام باطلة الرئيسية (سلسلة وسائط) { CountDownLatch مزلاج = CountDownLatch جديدة (2)؛ // إنشاء العد التنازلي المزلاج وتحديد عدد العد التنازلي 2 عامل W1 = عامل جديد ( "لوه هاو"، getRandomWorkDuration (MIN_WORK_DURATION، MAX_WORK_DURATION))؛ عامل W2 = عامل جديد ( "مطرقة الملك"، getRandomWorkDuration (MIN_WORK_DURATION، MAX_WORK_DURATION))؛ جديد الموضوع (WorkerTestThread الجديدة (W1، مزلاج)) بدء ()؛ جديد الموضوع (WorkerTestThread الجديدة (W2، مزلاج)) بدء ()؛ محاولة { latch.await ()؛ // الانتظار الروافد العد التنازلي مزلاج 0 System.out.println ( "تم الانتهاء من جميع وظائف!")؛ } صيد (InterruptedException ه) { e.printStackTrace ()؛ } } }

ConcurrentHashMap

ConcurrentHashMap HashMap الإصدار هو في بيئة متزامنة، قد أريد أن أسأل، منذ تم تعيينه عن طريق نوع الحاوية Collections.synchronizedMap الحصول على ذات ألوان، لماذا تحتاج ConcurrentHashMap ذلك؟ لأن مضت بواسطة ذات ألوان مجموعات الأدوات المتاحة لكامل HashMap كائن حاوية سوف تغلق عند قراءة وكتابة البيانات، بحيث المواضيع الأخرى لاستخدام الحاوية على أي حال لن تكون قادرة على الحصول على تأمين الكائن، وهو ما يعني أن الانتظار الخيط قفل للحصول على فرصة لأداء بعد خروجه من كتلة متزامنة. في الواقع، يتم تحديد HashMap لتخزين أزواج مفتاح القيمة برميل (برميل لحل الصراع التجزئة قدم) من خلال وظيفة تجزئة، لا تحتاج إلى قفل الحاوية بالكامل عند تعديل HashMap، على وشك قفل منقحة " دلو "على ذلك. بنية بيانات HashMap كما هو مبين في الشكل.

وبالإضافة إلى ذلك، قدمت أيضا طريقة التشغيل الذرية ConcurrentHashMap، على النحو التالي:

  • putIfAbsent: إذا لم يتم تعيينها إلى المفتاح المطابق، سيتم إضافته إلى HashMap.
  • إزالة: إذا كان المفتاح موجود وقيمة تساوي الدولة الحالية (يساوي المقارنة الحقيقية)، ثم إزالة تعيين مفتاح بالذرة
  • استبدال: استبدال عنصر خريطة الذرية

CopyOnWriteArrayList

CopyOnWriteArrayList هو بديل لArrayList في بيئة متزامنة. CopyOnWriteArrayList عند كتابة نسخة بإضافة دلالات لتجنب المشاكل الناجمة عن الوصول المتزامن، وهو ما يعني أن أي تغييرات في العمليات سيخلق نسخة من القائمة في الجزء السفلي، هناك سوف مكرر لا تواجه التعديلات غير متوقعة قبل الوسائل. وهذا مفيد لعدم متزامن بدقة مشاهد للقراءة والكتابة، لأنه يوفر أداء أفضل. وتذكر أنك تريد أن تقلل من استخدام الأقفال، لكان من المحتم أن اسقاط أداء (الوصول المتزامن إلى البيانات في قاعدة البيانات ليس هذا حدث لك؟ إذا كان الأمر كذلك يجب عليهم التخلي عن استخدام قفل تشاؤما وتأمين متفائل)، CopyOnWriteArrayList الواضح أيضا حساب الحصول على مساحة من الوقت (في عالم الكمبيوتر، الزمان والمكان وعادة ما تكون تناقضات لا يمكن التوفيق بينها، ويمكن التضحية الفضاء لتحسين الكفاءة للحصول على الوقت، بالطبع، من الممكن أيضا للحد من استخدام الفضاء على حساب الوقت).

يمكن التحقق من صحة رموز اثنين أدناه ما هو CopyOnWriteArrayList ليس ذات ألوان الحاوية.

استيراد java.util.ArrayList. استيراد java.util.List. استيراد java.util.concurrent.ExecutorService. java.util.concurrent.Executors الاستيراد؛ الطبقة AddThread الأدوات Runnable { قائمة خاصة < مزدوج >  القائمة؛ الجمهور AddThread (قائمة < مزدوج >  قائمة) { this.list = القائمة؛ } Override المدى باطلة العامة () { ل(كثافة العمليات ط = 0؛ ط <  10000؛ ++ ط) { list.add (Math.random ())؛ } } } الطبقة العامة Test05 { ساكنة الخاص نهائي الباحث THREAD_POOL_SIZE = 2؛ ساكنة العام باطلة الرئيسية (سلسلة وسائط) { قائمة < مزدوج >  قائمة = ArrayList جديد < > ()؛ ExecutorService وفاق = Executors.newFixedThreadPool (THREAD_POOL_SIZE)؛ es.execute (جديد AddThread (قائمة))؛ es.execute (جديد AddThread (قائمة))؛ es.shutdown ()؛ } }

رمز أعلاه ينتج ArrayIndexOutOfBoundsException في وقت التشغيل، حاول 25 خطوط من التعليمات البرمجية أعلاه ArrayList CopyOnWriteArrayList إلى العملية مرة أخرى.

قائمة < مزدوج >  قائمة = CopyOnWriteArrayList جديدة < > ()؛

طابور

بعدين هو مفهوم رائع في كل مكان، فإنه يوفر طريقة بسيطة وموثوق بها لتوزيع الموارد تجهيز وحدة (ويمكن القول أن يتم تعيين المورد إلى وحدة من العمل الذي يتعين معالجتها، وهذا يتوقف على الطريقة التي ننظر مشاكل) . العديد من تطبيقات نماذج البرمجة المتزامنة تعتمد طوابير لتنفيذ لأنه يمكن أن ينتقل بين وحدة المواضيع العمل.

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

ويمكن أن يتحقق مع BlockingQueue منتج - نموذج التوافق المستهلك (المقطع التالي هو عرض هناك)، قبل الدورة 5 جافا يمكن أيضا أن يتحقق عن طريق موضوع جدولة الانتظار وإعلام، قارن ونوعين من التعليمات البرمجية تعرف على أساس المرافق التزامن القائمة فئة لإعادة بناء التعليمات البرمجية المتزامنة في النهاية كانت جيدة.

واستنادا تحقيق الانتظار وإعلام

استيراد java.util.ArrayList. استيراد java.util.List. استيراد java.util.UUID. استيراد java.util.concurrent.ExecutorService. java.util.concurrent.Executors الاستيراد؛ / ** * الثوابت العامة *Author لوه هاو * * / الطبقة الثوابت { ساكنة العام النهائي كثافة MAX_BUFFER_SIZE = 10؛ ساكنة العام النهائي كثافة NUM_OF_PRODUCER = 2؛ ساكنة العام النهائي كثافة NUM_OF_CONSUMER = 3؛ } / ** * المهام *Author لوه هاو * * / الطبقة العمل { معرف سلسلة الخاص، وعدد من المهام // الجمهور المهام () { معرف = UUID.randomUUID () toString ()؛ } Override جمهور سلسلة toString () { عودة "العمل ". } } / ** * المستهلكين *Author لوه هاو * * / الطبقة المستهلك تنفذ Runnable { قائمة خاصة < مهمة >  العازلة. المستهلك العام (قائمة < مهمة >  عازلة) { this.buffer = العازلة؛ } Override المدى باطلة العامة () { بينما (صحيح) { تزامن (عازلة) { بينما (buffer.isEmpty ()) { محاولة { buffer.wait ()؛ } صيد (InterruptedException ه) { e.printStackTrace ()؛ } } مهمة مهمة = buffer.remove (0)؛ buffer.notifyAll ()؛ System.out.println ( "المستهلك حصلت" + المهام). } } } } / ** * المنتجون *Author لوه هاو * * / تنفذ الطبقة منتج Runnable { قائمة خاصة < مهمة >  العازلة. منتج العام (قائمة < مهمة >  عازلة) { this.buffer = العازلة؛ } Override المدى باطلة العامة () { بينما (صحيح) { تزامن (عازلة) { بينما (buffer.size () > = Constants.MAX_BUFFER_SIZE) { محاولة { buffer.wait ()؛ } صيد (InterruptedException ه) { e.printStackTrace ()؛ } } مهمة مهمة = مهمة جديدة ()؛ buffer.add (مهمة)؛ buffer.notifyAll ()؛ System.out.println ( "منتج ضع" + المهام). } } } } الطبقة العامة Test06 { ساكنة العام باطلة الرئيسية (سلسلة وسائط) { قائمة < مهمة >  عازلة = ArrayList جديد < > (Constants.MAX_BUFFER_SIZE)؛ ExecutorService وفاق = Executors.newFixedThreadPool (Constants.NUM_OF_CONSUMER + Constants.NUM_OF_PRODUCER)؛ ل(كثافة العمليات ط = 1؛ ط < = Constants.NUM_OF_PRODUCER، ++ ط) { es.execute (منتج جديد (عازلة))؛ } ل(كثافة العمليات ط = 1؛ ط < = Constants.NUM_OF_CONSUMER، ++ ط) { es.execute (المستهلك الجديد (عازلة))؛ } } }

واستنادا تحقيق BlockingQueue

استيراد java.util.UUID. استيراد java.util.concurrent.BlockingQueue. استيراد java.util.concurrent.ExecutorService. java.util.concurrent.Executors الاستيراد؛ استيراد java.util.concurrent.LinkedBlockingQueue. / ** * الثوابت العامة *Author لوه هاو * * / الطبقة الثوابت { ساكنة العام النهائي كثافة MAX_BUFFER_SIZE = 10؛ ساكنة العام النهائي كثافة NUM_OF_PRODUCER = 2؛ ساكنة العام النهائي كثافة NUM_OF_CONSUMER = 3؛ } / ** * المهام *Author لوه هاو * * / الطبقة العمل { معرف سلسلة الخاص، وعدد من المهام // الجمهور المهام () { معرف = UUID.randomUUID () toString ()؛ } Override جمهور سلسلة toString () { عودة "العمل ". } } / ** * المستهلكين *Author لوه هاو * * / الطبقة المستهلك تنفذ Runnable { BlockingQueue الخاص < مهمة >  العازلة. المستهلك العام (BlockingQueue < مهمة >  عازلة) { this.buffer = العازلة؛ } Override المدى باطلة العامة () { بينما (صحيح) { محاولة { مهمة مهمة = buffer.take ()؛ System.out.println ( "المستهلك حصلت" + المهام). } صيد (InterruptedException ه) { e.printStackTrace ()؛ } } } } / ** * المنتجون *Author لوه هاو * * / تنفذ الطبقة منتج Runnable { BlockingQueue الخاص < مهمة >  العازلة. منتج العام (BlockingQueue < مهمة >  عازلة) { this.buffer = العازلة؛ } Override المدى باطلة العامة () { بينما (صحيح) { محاولة { مهمة مهمة = مهمة جديدة ()؛ buffer.put (مهمة)؛ System.out.println ( "منتج ضع" + المهام). } صيد (InterruptedException ه) { e.printStackTrace ()؛ } } } } الطبقة العامة Test07 { ساكنة العام باطلة الرئيسية (سلسلة وسائط) { BlockingQueue < مهمة >  عازلة = LinkedBlockingQueue جديدة < > (Constants.MAX_BUFFER_SIZE)؛ ExecutorService وفاق = Executors.newFixedThreadPool (Constants.NUM_OF_CONSUMER + Constants.NUM_OF_PRODUCER)؛ ل(كثافة العمليات ط = 1؛ ط < = Constants.NUM_OF_PRODUCER، ++ ط) { es.execute (منتج جديد (عازلة))؛ } ل(كثافة العمليات ط = 1؛ ط < = Constants.NUM_OF_CONSUMER، ++ ط) { es.execute (المستهلك الجديد (عازلة))؛ } } }

بعد استخدام رمز BlockingQueue الكثير من الأناقة.

نموذج التوافق

قبل مناقشة ما يلي: متابعة، نذكر أنفسنا من بعض المفاهيم:

شرح مفهوم الموارد الحيوية بيئة متزامنة مع كمية محددة من الموارد وصول خاص إلى الموارد هو نوع خاص من الجوع أو مجموعة من المواضيع لفترة طويلة أو لن تكون قادرة على تقديم الجمود تقدم اثنين أو أكثر من المواضيع انتظر كل Livelock تريد الآخرين لنهاية خيط ليتم تنفيذها دائما وجدت موضوع آخر أن يتم تنفيذ لفترة طويلة أو غير قادرة بشكل دائم لأداء

بعد استعراض هذه المفاهيم، يمكننا استكشاف نموذج التزامن عدة التالية.

منتج - المستهلك

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

القارئ - الكاتب

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

الفلاسفة تناول الطعام

في عام 1965، طرح جائزة تورينج الفائز الهولندي عالم الكمبيوتر إدسجير Wybe ديكسترا وحل مشكلة تزامن دعا وجبة الفيلسوف. يمكن وصفها هذه المشكلة ببساطة على النحو التالي: خمسة الفلاسفة كانوا جالسين حول مائدة مستديرة، وأمام كل الفيلسوف ديه المعكرونة. منذ المعكرونة زلق جدا، لذلك فمن الضروري أن قبضة اثنين من الشوك. وضعت بين اثنين من لوحات المتاخمة لديها شوكة كما هو مبين أدناه. فيلسوف الحياة هناك اثنين بالتناوب فترات المفعلة: الأكل والتفكير. عندما يشعر بالجوع الفيلسوف، وقال انه حاول مرتين لاتخاذ الشوك في اليسار واليمين، كل لقطة واحدة، ولكن بغض النظر عن هذا الأمر. وإذا ما نجحت في الحصول على اثنين من الشوك، وقال انه يبدأ الأكل، وبعد تناول وضعت أسفل شوكة لمواصلة التفكير.

المشاكل المذكورة أعلاه الفيلسوف استبداله موضوع، وشوكة في التنافس على الموارد الحيوية، والمشكلة المذكورة أعلاه هي مشكلة المواضيع تتنافس على الموارد. إذا لم تكن مصممة بعناية، فإن النظام طريق مسدود، قفل الحية، وفقدان الإنتاجية وغيرها من المشاكل.

هنا هو الأوليات ملوحة لحل المشكلة الفلاسفة كود الطعام، وذلك باستخدام جافا 5 بالتزامن كيت سيمافور فئة (رمز ليست جميلة لكنها كانت كافية لشرح المشكلة).

// java.util.concurrent.ExecutorService الاستيراد؛ // java.util.concurrent.Executors الاستيراد؛ استيراد java.util.concurrent.Semaphore. / ** إشارة * المشتركة موضوع التخزين وصولا الى طرح *Author لوه هاو * * / الطبقة AppContext { ساكنة العام النهائي كثافة NUM_OF_FORKS = 5؛ // عدد من شوكة (موارد) الجمهور ساكنة نهائي الباحث NUM_OF_PHILO = 5؛ // عدد الفيلسوف (موضوع) ساكنة العام سيمافور الشوك؛ // شوكة الإشارة ساكنة العام سيمافور مكافحة؛ // الفلاسفة ملوحة ثابت { الشوك = سيمافور جديد . ل(كثافة العمليات ط = 0، ليون = forks.length، وأنا <  ليون، ++ ط) { الشوك  = جديد سيمافور (1)؛ // لكل شوكة عمود الاشارة 1 } مكافحة = جديد سيمافور (NUM_OF_PHILO - 1)؛ // إذا كان هناك N الفلاسفة، ويسمح بحد أقصى N-1 في وقت واحد أخذ شوكة الإنسان } / ** * الحصول على مفترق * مؤشرparam أول من عدة الفلاسفة *param leftFirst سواء للحصول على مفترق الطرق إلى اليسار *Throws InterruptedException * / ساكنة العام باطل putOnFork (مؤشر كثافة العمليات، منطقية leftFirst) يلقي InterruptedException { إذا (leftFirst) { الشوك .acquire ()؛ شوك .acquire ()؛ } آخر { شوك .acquire ()؛ الشوك .acquire ()؛ } } / ** * استبدال شوكة * مؤشرparam أول من عدة الفلاسفة *param leftFirst سواء ليحل محل الشوكة على اليسار *Throws InterruptedException * / ساكنة العام باطل putDownFork (مؤشر كثافة العمليات، منطقية leftFirst) يلقي InterruptedException { إذا (leftFirst) { الشوك .release ()؛ شوك .release ()؛ } آخر { شوك .release ()؛ الشوك .release ()؛ } } } / ** * الفيلسوف *Author لوه هاو * * / الطبقة الفيلسوف الأدوات Runnable { مؤشر كثافة العمليات الخاص؛ // عدد اسم سلسلة الخاص؛ اسم // الجمهور الفيلسوف (مؤشر كثافة العمليات، اسم سلسلة) { this.index = مؤشر. this.name = الاسم؛ } Override المدى باطلة العامة () { بينما (صحيح) { محاولة { AppContext.counter.acquire ()؛ منطقية leftFirst = مؤشر 2 == 0؛ AppContext.putOnFork (مؤشر، leftFirst)؛ System.out.println (اسم + "كان يأكل المعكرونة (الباستا) ...")؛ // يمكن اتخاذ اثنين الشوك لتناول الطعام AppContext.putDownFork (مؤشر، leftFirst)؛ AppContext.counter.release ()؛ } صيد (InterruptedException ه) { e.printStackTrace ()؛ } } } } الطبقة العامة Test04 { ساكنة العام باطلة الرئيسية (سلسلة وسائط) { سلسلة أسماء = { "لوه هو"، "وانغ مطرقة"، "تشانغ سان"، "يانغ قوه"، "ليمو تشو"}؛ // اسم 5 الفلاسفة // ExecutorService وفاق = Executors.newFixedThreadPool (AppContext.NUM_OF_PHILO)؛ // إنشاء تجمع موضوع حجم ثابت // ل(كثافة العمليات ط = 0، ليون = names.length، وأنا <  ليون، ++ ط) { // es.execute (الفيلسوف (ط، أسماء جديدة ))؛ // بدء موضوع //} // es.shutdown ()؛ ل(كثافة العمليات ط = 0، ليون = names.length، وأنا <  ليون، ++ ط) { جديد الموضوع (جديد الفيلسوف (ط، أسماء .)) ابدأ ()؛ } } }

مشاكل العالم الحقيقي المتزامنة هي في الأساس ثلاثة نماذج أو المتغيرات من هذه النماذج الثلاثة.

رمز الاختبار المتزامنة

رمز الاختبار المتزامنة هو صعب جدا، صعبة للوغني عن القول أننا جميعا درجة واضحة، لذلك هنا نناقش فقط كيفية حل هذه المشكلة الشائكة. نقترح أن تكتب بعض الاختبارات أن تجد المشاكل وكثرة تشغيل هذه الاختبارات في تكوينات مختلفة وحمولات مختلفة. لا تتجاهل أي اختبار الفشل، الخيوط العيوب البرمجية التي قد تحدث مرة واحدة فقط في مرات اختبار ألفا. على وجه التحديد، وهناك عدد قليل جدا من الملاحظات:

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

البرمجة المتزامنة في جافا 7

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

لقد نسيت شيئا واحدا، جافا 5 يدخل أيضا للاستدعاء واجهة، واجهات المستقبل FutureTask واجهات، كما أنها يمكن أن يتم بناؤها من قبل التطبيقات المتزامنة، الرمز المبين أدناه.

استيراد java.util.ArrayList. استيراد java.util.List. استيراد java.util.concurrent.Callable. استيراد java.util.concurrent.ExecutorService. java.util.concurrent.Executors الاستيراد؛ استيراد java.util.concurrent.Future. الطبقة العامة Test07 { ساكنة الخاص نهائي الباحث POOL_SIZE = 10؛ ساكنة تنفذ الطبقة CalcThread للاستدعاء < مزدوج >  { قائمة خاصة < مزدوج >  Datalist على = ArrayList جديد < > ()؛ الجمهور CalcThread () { ل(كثافة العمليات ط = 0؛ ط <  10000؛ ++ ط) { dataList.add (Math.random ())؛ } } Override دعوة الجمهور مزدوجة () رميات استثناء { مجموعه مزدوج = 0؛ ل(د مزدوج: Datalist على) { مجموعه + = د. } مجموعه عودة / dataList.size ()؛ } } ساكنة العام باطلة الرئيسية (سلسلة وسائط) { قائمة < مستقبل < مزدوج > >  fList = ArrayList جديد < > ()؛ ExecutorService وفاق = Executors.newFixedThreadPool (POOL_SIZE)؛ ل(كثافة العمليات ط = 0؛ ط <  POOL_SIZE، ++ ط) { fList.add (es.submit (CalcThread الجديدة ()))؛ } ل(المستقبل < مزدوج >  و: fList) { محاولة { System.out.println (f.get ())؛ } صيد (استثناء ه) { e.printStackTrace ()؛ } } es.shutdown ()؛ } }

واجهة للاستدعاء هو أيضا، أسلوب واحد واجهات، ومن الواضح أن هذا هو أسلوب الاستدعاء، على غرار وظيفة البرمجة رد الوظيفية في جاوة 8 قبل، جافا أيضا لا يمكن استخدام تعبيرات لامدا لتبسيط هذه البرمجة الوظيفية. واجهة Runnable مختلفة استدعاء أسلوب الاستدعاء طريقة سيعود كائن واجهة للاستدعاء الذي يمكن الحصول على معلومات في وقت تنفيذ موضوع بحلول نهاية الطريق عندما المستقبل. استدعاء الأسلوب هو رمز المذكور بين متوسط قيمة عشري عشوائي 100000-1 احتساب المقابل، نحصل على قيمة الإرجاع للكائن واجهة المستقبل. يتم وضع علامة على أحدث نسخة من جافا، للاستدعاء واجهة Runnable واجهات مع شروحFunctionalInterface، مما يعني أنه يمكن إنشاء كائنات واجهة مع وضع برمجة وظيفية (تعبيرات لامدا).

هنا واجهة أسلوب المستقبل رئيسية:

  • الحصول على (): الحصول على النتائج. إذا كانت النتائج ليست جاهزة بعد، والحصول على كتل الطريقة حتى تحصل على نتائج، وبالطبع، يمكن أيضا أن يكون قد تم حظره بواسطة إعدادات المعلمة المهلة.
  • إلغاء (): إلغاء قبل نهاية العملية.
  • isDone (): يمكن استخدامه لتحديد ما إذا كان لانهاء العملية.

يتم توفير 7 أيضا في فرع / (شوكة / الانضمام) إطار جافا، وجدولة التلقائي من المواضيع في بركة من المهام التي يمكن تنفيذها، وهذا الجدول هو شفافا بالنسبة للمستخدم. ولهذه الغاية، يجب أن تتحلل المهمة في بالطريقة التي يحددها المستخدم، ومن ثم نتيجة تنفيذ المهام الصغيرة، ثم تتحلل إلى النتيجة الإجمالية لتنفيذ المهمة الأصلية. هذا ومن الواضح أن فكرة استخدام فرق تسد (فرق وتسد) أ. تستخدم التعليمة البرمجية التالية إطار فرع / دمج لحساب و1-10000، بطبيعة الحال، لهذه المهمة بسيطة لا تحتاج إلى إطار فرع / دمج، منذ المتفرعة ودمجها في حد ذاته سوف يجلب بعض النفقات العامة، ولكن هنا نستكشف فقط كيفية استخدام المتفرعة / دمج في إطار القانون، لذلك هذا الرمز لدينا يمكن الاستفادة من قدرات حوسبة قوية من وحدة المعالجة المركزية الحديثة متعددة النواة.

استيراد java.util.concurrent.ForkJoinPool. استيراد java.util.concurrent.Future. استيراد java.util.concurrent.RecursiveTask. الطبقة حاسبة يمتد RecursiveTask < عدد صحيح >  { خاص ثابت نهائي طويلة serialVersionUID = 7333472779649130114L. ساكنة الخاص كثافة النهائي العتبة = 10؛ بداية كثافة العمليات الخاص؛ نهاية كثافة العمليات الخاصة؛ الجمهور حاسبة (بداية كثافة العمليات، نهاية كثافة العمليات) { this.start = بدء؛ this.end = الغاية؛ } Override الجمهور صحيح حساب () { مبلغ كثافة العمليات = 0؛ إذا ((نهاية - بداية) <  العتبة) {// عندما يمكن حل المشكلة بشكل مباشر إلى درجة التحلل من حساب النتائج ل(كثافة العمليات ط = بدء؛ ط < = النهاية، وأنا ++) { المبلغ + = ط. } } {شيء آخر = الوسطى INT (بدء + النهاية) > > >  1؛ // مهمة إلى قسمين غادر حاسبة = آلة حاسبة جديدة (بداية والمتوسطة)؛ آلة حاسبة الحق = آلة حاسبة جديدة (المتوسطة + 1، نهاية)؛ left.fork ()؛ right.fork ()؛ // ملاحظة: لأن هنا هو التحلل مهمة متكررة، مما يعني أن القادم سيكون اثنين إلى أربعة، وأربعة إلى ثمانية ... مبلغ = left.join () + right.join ()؛ تم الجمع بين // النتائج في اثنين من المهام الفرعية } العودة المبلغ. } } الطبقة العامة Test08 { ساكنة العام باطلة الرئيسية (سلسلة وسائط) رميات استثناء { ForkJoinPool forkJoinPool = ForkJoinPool جديدة ()؛ مستقبل < عدد صحيح >  يؤدي = forkJoinPool.submit (حاسبة جديدة (1، 10000))؛ System.out.println (result.get ())؛ } }

مع ظهور جافا 7، الافتراضي جافا مجموعة خوارزمية الفرز لم يعد نوع كلاسيكي سريع (محور سريعة نوع مزدوج)، خوارزمية الفرز جديدة تسمى TimSort، بل هو مزيج من نوع دمج وإدراج النوع، TimSort يمكن دمج إطار فرع الاستفادة من خصائص المعالجات متعددة النواة الحديثة، يؤدي إلى أداء أفضل (مرات فرز أقصر).

شيان رجل مع لوحة عرض قناة الصغرى وقطع الحسابات غير مألوفة، فضلا عن أوامر غير دفع خارج الموقع

واستمر المساهمين النبيذ القديم هناك حقيقة، "نظرا زعيم المجلس الثاني" لترتفع 10 زعيم المجلس المهارات الفريدة حقا لسيده ويمكنك التقاط المجلس حتى عشر المقبل

الصفحة الأولى اليوم من الدوري الأسباني: أتلتيكو مدريد توقع M- لورينتي Kudiniao أكثر للذهاب إلى باريس

افتتح مجلس ابتكار العلوم والتكنولوجيا اليوم ، ومن المرجح أن تكون هذه الأسهم أكبر الرابحين

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

هذا هو أفضل ما رأيت من أي وقت مضى استراتيجية التداول: "EMA + MACD" مزيج مثالي، ودعا صناعة الكتاب المدرسي الأسهم، لا تحتاج إلى أسهم في السيطرة على الجسد

حصل في سوق الأسهم يصب والناس نخجل من "ثمانية أنواع من حيث الشكل"، واجه ركض مرة أخرى، وإلا فإن الحدث سيكون بالتأكيد أنهار من الدماء

مجلس فرع القادمة! ملحمة "الحفاز"، ومن المتوقع هذه الأسهم إلى إعصار

وارتفعت أسهم بعد تعديل لمدة يومين، وغدا أيضا ذلك؟

سوق الأسهم لكسب ثلاثة ملايين من نهج أكثر "غبي": أصر مرارا وتكرارا "MACD" 9 المهارات التجارية الكبرى وصناديق صغيرة يمكن أن تحول 10 مرات، من الفقر إلى الغنى

A الوطني "القيام T" الماشية الأولى إلى الدرجة الأسهم على لي: هل التداول يست متكررة، حاملا عصا طويلة مع أسهم T يوميا، ما لا يقل عن 35 أسبوع

نجا من "الخميس الأسود"، والاتجاه كيف ستكون غدا؟