English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

تفسير شامل للتوافق بين جداول البيانات في Java

تنفيذ List interface لعدد المتغير من مصفوفات. يحقق جميع العمليات الاختيارية للقائمة، ويسمح بإدراج جميع العناصر بما في ذلك null. بالإضافة إلى تنفيذ List interface، يوفر هذا النوع بعض الطرق لضبط حجم المصفوفة التي تستخدمها لتخزين القائمة. (يبدو هذا النوع تقريبًا مثل Vector class، باستثناء أن هذا النوع ليس متزامنًا.) تشغيل العمليات size، isEmpty، get، set، iterator و listIterator بوقت ثابت. تشغيل عملية add بوقت ثابت الموزع، مما يعني أن إضافة n عنصر يتطلب وقت O(n). تشغيل جميع العمليات الأخرى بوقت خطي (بشكل عام). مقارنة بالمعاملات الثابتة المستخدمة في تنفيذ LinkedList، تكون المعاملات الثابتة في هذا التنفيذ أقل. لكل نموذج ArrayList، هناك قدرة. هذه القدرة تشير إلى حجم مصفوفة المستخدمة لتخزين عناصر القائمة. وهي دائمًا تساوي أو تزيد عن حجم القائمة. مع إضافة العناصر إلى ArrayList، ينمو حجمها تلقائيًا. لم يتم تحديد تفاصيل استراتيجية النمو، لأن هذا ليس مجرد أن إضافة العناصر يسبب تكاليف ثابتة موزعة. يمكن للبرنامج استخدام عملية ensureCapacity لزيادة قدرة نموذج ArrayList عند إضافة عدد كبير من العناصر. هذا يمكن أن يقلل من عدد التوزيعات التدرجية.

الاحتواذ، هذه التنفيذ ليس متزامناً.

إذا كان عدة نواة تصل إلى نموذج ArrayList في نفس الوقت، وكان على الأقل واحدة منها تعديل هيكل القائمة، فإنه يجب أن يكون هناك توازي خارجي. (تعديل هيكل يشمل أي إضافة أو إزالة لعدة عناصر، أو تعديل حجم مصفوفة أساسية؛ ليس تعديل قيمة العنصر تعديل هيكل.) يتم إكمال هذا عادةً عن طريق تعديل الجسم الطبيعي الذي يحتوي على القائمة. إذا لم يكن هناك مثل هذا الجسم، فيجب استخدام طريقة Collections.synchronizedList لـ 'حزم' القائمة. من الأفضل القيام بذلك عند إنشاء القائمة لتجنب الوصول غير المتزامن غير المتوقع إلى القائمة:

Listlist = Collections.synchronizedList(newArrayList(...));

هذه الطريقة للiterator وlistIterator تعود استدلالات فاشلة بسرعة: بعد إنشاء الاستدلال، ما لم يتم تعديل هيكل القائمة من خلال طريقة remove أو add الخاصة بالاستدلال نفسه، فإن أي تعديل يتم على القائمة بأي طريقة في أي وقت، سيؤدي إلى إطلاق استثناء ConcurrentModificationException. لذلك، في مواجهة التعديلات المتوازية، يفشل الاستدلال بسرعة بدلاً من المخاطرة بتصرفات غير معروفة في وقت غير معلوم في المستقبل.

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

كما هو موضح أعلاه، الآن يتم إنشاء مجموعة list، thread واحد للكتابة على المجموعة، thread آخر للإزالة

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
public class MyArrayList {
	/** 
   * إنشاء قائمة، thread واحدة للكتابة، thread أخرى للقراءة iterator و listIterator يرجعان إلى م迭代ر سريع الفشل 
   */
	public void readWrite() {
		List<Integer> nums = new ArrayList<Integer>();
		List<Integer> synNums = Collections.synchronizedList(nums);
		// تشغيل عملية الكتابة 
		new WriteListThread(synNums).start();
		// تشغيل عملية الحذف 
		new DeleteListThread(synNums).start();
	}
	public static void main(String[] args) {
		new MyArrayList().readWrite();
	}
}
class WriteListThread extends Thread {
	private List<Integer> nums;
	public WriteListThread(List<Integer> nums) {
		super(“WriteListThread”);
		this.nums = nums;
	}
	// تأكيد كتابة العنصر 1 
	public void run() {
		while (true) {
			nums.add(new Random().nextint(1000));
			System.out.println(Thread.currentThread().getName());
		}
	}
}
class DeleteListThread extends Thread {
	private List<Integer> nums;
	public DeleteListThread(List<Integer> nums) {
		super(“DeleteListThread”);
		this.nums = nums;
	}
	// إزالة العنصر الأول 
	public void run() {
		while (true) {
			try{
				System.out.println(Thread.currentThread().getName()+":"+nums.remove(0));
			}
			catch(Exception e){
				continue ;
			}
		}
	}
}

من خلال List<Integer> synNums = Collections.synchronizedList(nums) يمكن تنفيذ العمليات الذرية المشروعة، ولكن لماذا يضيف API الرسمي مثال على القيام بذلك يدويًا؟

List list = Collections.synchronizedList(new ArrayList()); 
 synchronized(list) { 
   Iterator i = list.iterator(); // يجب أن يكون في قفل متزامن 
   while (i.hasNext()) 
     foo(i.next()); 
 } 

مراجعة ملف المصدر لـ Collections.synchronizedList

SynchronizedCollection(Collection<E> c) { 
      if (c==null) 
        throw new NullPointerException(); 
    this.c = c; 
      mutex = this; 
    } 
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
public class MyArrayList {
	/** 
   * إنشاء قائمة، thread واحدة للكتابة، thread أخرى للقراءة iterator و listIterator يرجعان إلى م迭代ر سريع الفشل 
   */
	public void readWrite() {
		List<Integer> nums = new ArrayList<Integer>();
		List<Integer> synNums = Collections.synchronizedList(nums);
		// تشغيل عملية الكتابة 
		new WriteListThread(synNums).start();
		// تشغيل عملية الحذف 
		new DeleteListThread(synNums).start();
	}
	public static void main(String[] args) {
		new MyArrayList().readWrite();
	}
}
class WriteListThread extends Thread {
	private List<Integer> nums;
	public WriteListThread(List<Integer> nums) {
		super("WriteListThread");
		this.nums = nums;
	}
	// تأكيد كتابة العنصر 1 
	public void run() {
		while (true) {
			nums.add(new Random().nextint(1000));
			System.out.println(Thread.currentThread().getName());
		}
	}
}
class DeleteListThread extends Thread {
	private List<Integer> nums;
	public DeleteListThread(List<Integer> nums) {
		super("DeleteListThread");
		this.nums = nums;
	}
	// إزالة العنصر الأول 
	public void run() {
		while (true) {
			try{
				System.out.println(Thread.currentThread().getName()+":"+nums.remove(0));
			}
			catch(Exception e){
				continue ;
			}
		}
	}
}

يظهر أن لعملية التزامن للمجموعة، باستخدام أدوات التزامن في Collections، يجب أن يتم الالتزامن يدويًا أيضًا لعمليات غير الذرية

كما يظهر في الصورة، أضف عملية اقرأ، لقراءة المجموعة

class ReadListThread extends Thread {
	private List<Integer> nums;
	public ReadListThread(List<Integer> nums) {
		super(“ReadListThread”);}}
		this.nums = nums;
	}
	//القراءة المستمرة للأعضاء، عملية غير أتمومية، لذا يجب إضافة المفتاح يدويًا 
	public void run() {
		while (true) {
			//الاستغناء، وإعطاء المفتاح لأخرى 
			try {
				Thread.sleep(1000);
			}
			catch (InterruptedException e1) {
				e1.printStackTrace();
			}
			synchronized (nums) {
				if (nums.size() > 100) {
					Iterator<Integer> iter = nums.iterator();
					while (iter.hasNext()) {
						System.out.println(Thread.currentThread().getName()) 
						                + ”:” + iter.next());
						;
					}
				} else{
					try {
						nums.wait(1000);
					}
					catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}
}

الخاتمة

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

بيان: محتوى هذا المقال تم جمعه من الإنترنت، ويحق لصاحب الحقوق أن يكون المسؤول عنه، تم إضافة المحتوى من قبل مستخدمي الإنترنت بطرق مستقلة، هذا الموقع لا يملك حقوق الملكية، لم يتم تعديل المحتوى بشكل يدوي، ولا يتحمل أي مسؤولية قانونية ذات صلة. إذا كنت قد وجدت محتوى يشتبه في حقوق النسخ، فيرجى إرسال بريد إلكتروني إلى: notice#oldtoolbag.com (عند إرسال البريد الإلكتروني، يرجى استبدال # ب @) لإبلاغنا، وقدم الدليل على الدليل، إذا تم التحقق من صحة الأمر، سيتم حذف المحتوى المزعوم عن حقوق النسخ على الفور.

سيكون ممتعاً لك