التزامن وتعدد الخيوط في 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(); // إنهاء التجمع بعد تنفيذ جميع المهام }}الأنواع الرئيسية للتجمعات:
newFixedThreadPool(n)— عدد ثابت من الخيوط-
المدونات
توصيات الكتب
اقرأ أيضًا