الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

لمحة جافاوية 56: كرر لكل عنصر في ضوء تعدد الخيوط

بدأه علاء الصالحي في 19 أغسطس 2009 · 7 رد · 804 مشاهدة · في JavaSE
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم

نقلت لكم هذه اللمحة من مدونتي لتعم الفائدة

يقول المتنبي

كفى بك داءاً أن ترى الموت شافياً

وحسب المنايا أن يكن أمانياً

المعنى أن أسوأ الداء هو الداء الذي يتمنى صاحبه الموت

وأسوأ أنواع الحياة الحياة التي يتمنى صاحبها الموت

لماذا أذكر هذه الأبيات لكم؟

ما من سبب يذكر

كل ما هناك أني أعجبت بهذا البيت

فقررت أن أضعه بين أيديكم

على كل دعونا من هذا ولأكلمكم عن لمحة اليوم

اطلعوا على الشيفرتين التاليتين وأخبروني هل هناك فرق

Vector<Integer> integers = new Vector<Integer>();
for (Integer i : integers) {
	System.out.println(i);
}

Vector<Integer> integers = new Vector<Integer>();
for (int j = 0; j < integers.size(); j++) {
	System.out.println(j);
}

طبعاً من النظرة الأولى يتضح لي أننا قمنا بطباعة العناصر الموجودة في الكائن integers

على كل هذا جميل جداً

جربوا الشيفرتين وأخبروني هل حصلتم على نفس النتيجة

(صحيح نفس النتيجة لا أحب أسلوب الحواة هذا هات ما عندك وارحمنا)

ممممممممممممممممممممممم

بالطبع ستحصلوا على نفس النتيجة

لكنكم لم تسألوا أنفسكم لماذا استخدمت كائن من نوع Vector

وأنا لا أنفك عن تذكيركم بأن Vector مكلفة جداً

بالطبع أنا أريدكم أن تجربوا الشيفرتين السابقتين في وجود تعدد خيوط Multithreading

(هذا أمر صعب جداً ما رأيك أن تضع الشيفرة كاملة)

أعتقد أني علمتكم الكثير من الأمور

لذا لا أعتقد أن هذا الأمر صعب عليكم

(إما أن تعطينا الشيفرة أو سأعمل(بفتح السين وضم العين) في رقبتك شفرة حلاقة حافية)

اعععععع

لا يا عم عبده إلا زعلك

هذه الشيفرة ضعوا فيها الشيفرتين السابقتين وهاتوا ملاحظاتكم

package iter;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

public class Test {
	Vector<Integer> integers = new Vector<Integer>();

	public Test() {
		// integers=Collections.synchronizedList(integers);
		int i = 0;
		while (i < 1000) {
			integers.add(i++);
		}
		Thread iterate = new Thread(new Runnable() {

			public void run() {
				//هنا ضعوا الشيفرتين السابقتين بدون أول سطر
			}
		});
		iterate.start();
		System.out.println(integers.size());
		Thread iterate2 = new Thread(new Runnable() {

			public void run() {
				while (i < 100) {
					integers.add(20);
					i++;
					System.out.println("th2");
				}

			}
		});
		iterate2.start();
	}

	public static void main(String[] args) {
		new Test();
	}
}

في الشيفرة code السابقة استخدمت خيطين

الخيط thread الأول يقوم بطباعة عناصر المتجه vector

والخيط thread الثاني يضيف على المتجه vector

(استخدمت التكرار loop في الخيط الثاني لضمان أن يحصل عملية إضافة وعملية طلب على المتجه في نفس الوقت)

ماذا تلاحظون عند وضع الشيفرتين في الشيفرة السابقة

الشيفرة الأولى تعطي خطأً اسمه java.util.ConcurrentModificationException

الشيفرة الثانية تعمل بشكل جيد

وهذا يعني أن الشيفرة الأولى غير آمنة في تعدد الخيوط Thread unsafe

إلى هنا يمكننا أن نقول أن اللمحة الخاصة بنا انتهت

ما سيأتي بعد هذا هو زيادة من عندي للتوضيح لمن أراد أن يعرف أكثر

السبب في كون الشيفرة الأولى أعطت هذا الخطأ

أن foreach تعتمد على Iterator في التعامل مع العناصر

والتعامل مع الفئة Iterator لا يكون مأمون العواقب إلا لو تم كله مرة واحدة

بمعنى يجب أن تكون الشيفرة كالتالي

Vector<Integer> integers = new Vector<Integer>();
synchronized(integers){
	for (Integer i : integers) {
		System.out.println(i);
	}
}

طبعاً هذه عملية مكلفة جداً وغير مجدية بالنسبة لنا

على كل ربما يحتاج لها أحد لسبب لا أعلمه

استنتاج ذكي:

ليس كل جديد جيد دائماً

(من قال أن التكرار لكل عنصر foreach جديد يا حيوان)

لا أعرف لماذا أنت رقيق في ألفاظك يا أخ عبده

على كل قصدت أنها أحدث من التكرار العادي

كالعادة أي أسئلة أنا في الخدمة

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#2

مقاله جيده, جزاك الله خيرا

#3

شكرا يا علاء على المقالة، وعارف أني جاي متأخر :blush: لكني ما انتبهت لها من قبل

وفعلا ملاحظة مهمة بخصوص الiterator، وسأنتبه لها من الآن فصاعدا، مع أن كل ما له علاقة بالthreads يسبب لي صداعا حادا :lol:

#4

بأمانة الموضوع أعقد مما تتصور

بالنسبة للخيوط threads كلما توقعت أني أعرف عنها كل شيء وجدت نفسي أجهل عنها أكثر مما أعرف

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#5

عجبتنى المقالة

---------------

لكن كالعادة لازم فى البداية اسال سوال بعيد عنها شوية

-------------------------------------------------

كتبت الكود بنفسى

كما كاتبه انت يا عم علاء :lol:

انظر بنفسك

------------

import java.util.Vector;

public class Test {

	private Vector<Integer> integers = new Vector<Integer>();
	private Thread iterate1, iterate2;

	public Test() {
		int i = 0;
		while (i < 1000) {
			integers.add(i++);
		}
		iterate1 = new Thread(new Runnable() {

			public void run() {
				for (Integer i : integers) {
					System.out.println(i);
				}
				for (int j = 0; j < integers.size(); j++) {
					System.out.println(j);
				}
			}
		});
		iterate1.start();
		System.out.println(integers.size());
		iterate2 = new Thread(new Runnable() {

			public void run() {
				while (i < 100) {
					integers.add(20);
					i++;
					System.out.println("HIII");

				}
			}
		});
		iterate2.start();
	}

	public static void main(String[] args) {
		new Test();
	}
}

فى الجزئية هذه :

---------------------

	while (i < 100) {
					integers.add(20);
					i++;

بيقولى make I final

هل ظهر معاك مثل هذا ؟؟ و لا انا كاتب غلط و لا ايه ؟؟؟

يلا جاوبنى عشان اجرب اكتشافك يا باشا

------------

شكراً

#6

أنا قلت هنا ضعوا الشيفرتين قصدت أحد االشيفرتين وليس كليهما

بالنسبة للخطأ الذي حصلت عليه فأنا لم أحصل عليها

لكن الكومبايلر صادق تماماً

ويستحق التغيير :)

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#8

اجعل الكود هكذا:

		Thread iterate2 = new Thread(new Runnable() {
			int i=0;

ملاحظه: لا يمكنك استخدام متغير في كلاس داخلي معرف في كلاس خارجي الا اذا عرفته final

شكرا أخ علاء على المعلومه المفيده.

تم تعديل هذه المشاركة بواسطة muqawem في 21 سبتمبر 2009 في 20:17

مواضيع مشابهة

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…