التزامن وتعدد الخيوط في Java: دليل شامل

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

التزامن وتعدد الخيوط في Java: من النظرية إلى التطبيق



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



ما هو الخيط وكيف يتم إنشاؤه في Java؟



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



الطريقة 1: الوراثة من فئة Thread

public class MyThread extends Thread {    @Override    public void run() {        System.out.println("الخيط " + getName() + " تم تشغيله!");    }

public static void main(String[] args) { MyThread thread = new MyThread(); thread.start(); // تشغيل الخيط }}


الطريقة 2: تنفيذ واجهة Runnable

public class MyRunnable implements Runnable {    @Override    public void run() {        System.out.println("الخيط يعمل عبر Runnable");    }

public static void main(String[] args) { Thread thread = new Thread(new MyRunnable()); thread.start(); }}


يوصى باستخدام الطريقة الثانية لأنها لا تتطلب الوراثة وتسمح بتنفيذ واجهات متعددة في نفس الوقت.



مزامنة الخيوط: تجنب حالة السباق



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



الكلمة المفتاحية synchronized

تمنع الوصول إلى طريقة أو كتلة من الكود للخيوط الأخرى حتى ينتهي الخيط الحالي من التنفيذ:

public class Counter {    private int count = 0;

public synchronized void increment() { count++; }

public synchronized int getCount() { return count; }}


الأقفال باستخدام Lock

آلية أكثر مرونة من synchronized. تسمح بتعيين مهلات زمنية ومحاولة الحصول على القفل دون حظر:

import java.util.concurrent.locks.ReentrantLock;

public class SafeCounter { private final ReentrantLock lock = new ReentrantLock(); private int count = 0;

public void increment() { lock.lock(); try { count++; } finally { lock.unlock(); // نقوم دائمًا بتحرير القفل } }}


تجمع الخيوط و ExecutorService



إنشاء خيط جديد لكل مهمة هو عملية مكلفة. لإدارة الخيوط بكفاءة، استخدم ExecutorService من الحزمة java.util.concurrent.



import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;

public class ThreadPoolExample { public static void main(String[] args) { // إنشاء تجمع من 4 خيوط ExecutorService executor = Executors.newFixedThreadPool(4);

for (int i = 0; i < 10; i++) { final int taskId = i; executor.submit(() -> { System.out.println("المهمة " + taskId + " تُنفذ في " + Thread.currentThread().getName()); }); }

executor.shutdown(); // إنهاء التجمع بعد تنفيذ جميع المهام }}


الأنواع الرئيسية للتجمعات: