البرمجة المتزامنة (Multithreading) في جافا
ما هي البرمجة المتزامنة (Multithreading) في جافا؟
البرمجة المتزامنة (Multithreading) هي طريقة لتنفيذ عمليات متعددة في نفس الوقت داخل برنامج واحد. في جافا، تُستخدم الخيوط (Threads) لتقسيم البرنامج إلى مهام متعددة يمكن تنفيذها بشكل متزامن، مما يساعد على تحسين أداء البرامج، خاصةً عند تنفيذ مهام معقدة مثل العمليات الحسابية الكبيرة، قراءة الملفات، أو الاستجابة لمدخلات المستخدم.
ما هو الـ Thread في جافا؟
الـ Thread هو وحدة مستقلة من التنفيذ يمكن أن تعمل بشكل متوازي مع خيوط أخرى في نفس البرنامج. يمكن استخدام الخيوط لتنفيذ مهام متعددة بشكل متزامن. عند إنشاء برنامج يحتوي على خيوط متعددة، يتم إنشاء “برنامج متعدد الخيوط” (Multithreaded Program).
كيفية إنشاء الخيوط (Threads) في جافا
يمكنك إنشاء الخيوط في جافا بطريقتين:
- **وراثة الفئة Thread:** يتم إنشاء فئة فرعية من الفئة
Thread
وتجاوز (Override) الدالةrun
لتنفيذ الكود. - **تنفيذ واجهة Runnable:** يتم إنشاء فئة تنفذ (Implement) واجهة
Runnable
، ثم تمرير الكائن إلى كائن من الفئةThread
.
الطريقة الأولى: وراثة الفئة Thread
يمكنك إنشاء فئة فرعية من الفئة Thread
، وتجاوز (Override) الدالة run
، ثم إنشاء كائن من هذه الفئة لتشغيل الخيط:
class MyThread extends Thread {
public void run() {
System.out.println("الخيط يعمل الآن!");
}
}
public class Main {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start(); // بدء تشغيل الخيط
}
}
في هذا المثال، قمنا بإنشاء فئة MyThread
ترث من الفئة Thread
، وتجاوزنا الدالة run
لتنفيذ الكود. ثم قمنا بإنشاء كائن من هذه الفئة، واستخدمنا الدالة start
لتشغيل الخيط.
الطريقة الثانية: تنفيذ واجهة Runnable
يمكنك إنشاء خيط عن طريق تنفيذ واجهة Runnable
، ثم تمرير الكائن إلى كائن من الفئة Thread
:
class MyRunnable implements Runnable {
public void run() {
System.out.println("الخيط يعمل الآن!");
}
}
public class Main {
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start(); // بدء تشغيل الخيط
}
}
في هذا المثال، قمنا بإنشاء فئة MyRunnable
التي تنفذ واجهة Runnable
، ثم قمنا بإنشاء كائن من الفئة Thread
ومررنا الكائن runnable
إليه. بعد ذلك، استخدمنا الدالة start
لتشغيل الخيط.
الفرق بين start() و run()
عند إنشاء خيط جديد، يجب استدعاء الدالة start
، وليس run
. إذا استدعيت run
مباشرةً، سيتم تنفيذ الكود في الخيط الرئيسي، وليس في خيط منفصل.
التزامن (Synchronization) في جافا
عند التعامل مع خيوط متعددة، قد يحدث أن يقوم أكثر من خيط بالوصول إلى نفس البيانات في نفس الوقت، مما قد يؤدي إلى نتائج غير صحيحة. لحل هذه المشكلة، يمكنك استخدام التزامن (Synchronization) لتأمين البيانات عند استخدامها من قبل أكثر من خيط.
يمكنك استخدام الكلمة المفتاحية synchronized
لتأمين دالة أو كتلة كود. الصيغة العامة هي:
synchronized(object) {
// الكود الذي سيتم تأمينه
}
أو لتأمين دالة كاملة:
synchronized void methodName() {
// الكود الذي سيتم تأمينه
}
مثال:
class Counter {
private int count = 0;
synchronized void increment() {
count++;
}
int getCount() {
return count;
}
}
public class Main {
public static void main(String[] args) {
Counter counter = new Counter();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
t1.start();
t2.start();
try {
t1.join(); // انتظار انتهاء الخيط الأول
t2.join(); // انتظار انتهاء الخيط الثاني
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("القيمة النهائية: " + counter.getCount());
}
}
في هذا المثال، قمنا بإنشاء فئة Counter
تحتوي على دالة increment
لتأمين زيادة قيمة count
باستخدام الكلمة المفتاحية synchronized
. يتم استخدام خيطين لزيادة القيمة 1000 مرة لكل منهما، ثم يتم طباعة النتيجة النهائية.
تمرين (مستوى متوسط): إنشاء برنامج لحساب مجموع الأعداد باستخدام الخيوط
في هذا التمرين، سنقوم بإنشاء برنامج لحساب مجموع الأعداد من 1 إلى 1000 باستخدام خيطين. سيتم تقسيم الأعداد إلى نصفين، ويقوم كل خيط بحساب المجموع للنصف الخاص به.
المتطلبات:
- إنشاء فئة
SumCalculator
التي تنفذRunnable
وتحسب مجموع الأعداد من بداية إلى نهاية معينة. - استخدام خيطين لحساب مجموع الأعداد من 1 إلى 500، و 501 إلى 1000.
- إظهار المجموع الكلي بعد انتهاء الخيطين من الحساب.
الكود:
class SumCalculator implements Runnable {
private int start;
private int end;
private int sum;
SumCalculator(int start, int end) {
this.start = start;
this.end = end;
}
public void run() {
sum = 0;
for (int i = start; i <= end; i++) {
sum += i;
}
}
int getSum() {
return sum;
}
}
public class Main {
public static void main(String[] args) {
SumCalculator calculator1 = new SumCalculator(1, 500);
SumCalculator calculator2 = new SumCalculator(501, 1000);
Thread thread1 = new Thread(calculator1);
Thread thread2 = new Thread(calculator2);
thread1.start();
thread2.start();
try {
thread1.join(); // انتظار انتهاء الخيط الأول
thread2.join(); // انتظار انتهاء الخيط الثاني
} catch (InterruptedException e) {
e.printStackTrace();
}
int totalSum = calculator1.getSum() + calculator2.getSum();
System.out.println("المجموع الكلي: " + totalSum);
}
}
شرح الكود:
- قمنا بإنشاء فئة
SumCalculator
التي تحسب مجموع الأعداد من بداية إلى نهاية محددة. - استخدمنا خيطين لحساب مجموع الأعداد من 1 إلى 500، و 501 إلى 1000.
- استخدمنا الدالة
join
لانتظار انتهاء كلا الخيطين، ثم قمنا بجمع النتائج وطباعة المجموع الكلي.
جرّب تنفيذ هذا البرنامج بنفسك، وشارك نتيجتك معنا في التعليقات! إذا واجهتك أي مشكلة أو كان لديك سؤال، لا تتردد في طرحه.
خاتمة
في هذا الدرس، تعرفنا على البرمجة المتزامنة في جافا، وكيفية إنشاء الخيوط والتحكم فيها باستخدام الفئات وواجهة Runnable
. كما تعرفنا على التزامن وكيفية تأمين الكود عند تنفيذ عمليات متعددة. نوصي بممارسة التمرين المقدم لاكتساب المزيد من الخبرة. لا تنسَ ترك تعليق أو مشاركة هذا الدرس مع أصدقائك على وسائل التواصل الاجتماعي إذا وجدته مفيدًا!
اترك تعليقاً