Atefeh Tahbaz
Atefeh Tahbaz
خواندن ۵ دقیقه·۴ ماه پیش

راهنمای جامع مالتی تردینگ (Multithreading) در جاوا + مثال‌های کاربردی

multi threading
multi threading


مقدمه

مالتی تردینگ (Multithreading) در جاوا یک قابلیت قدرتمند است که به برنامه‌ها اجازه می‌دهد چندین کار را به صورت هم‌زمان اجرا کنند. این ویژگی باعث افزایش کارایی برنامه و استفاده بهتر از منابع سخت‌افزاری می‌شود. در این مقاله، به معرفی مفهوم مالتی تردینگ، نحوه پیاده‌سازی آن در جاوا و مدیریت تردها خواهیم پرداخت.

۱. مالتی تردینگ چیست؟

مالتی تردینگ به معنای اجرای هم‌زمان چندین رشته پردازشی (Thread) در یک برنامه است. در جاوا، هر برنامه حداقل یک ترد اصلی (Main Thread) دارد که اجرای برنامه را کنترل می‌کند.

مزایای استفاده از مالتی تردینگ

افزایش کارایی برنامه
استفاده بهینه از پردازنده (CPU Utilization)
کاهش زمان پاسخگویی در برنامه‌های گرافیکی و شبکه‌ای
اجرای چندین وظیفه به‌طور هم‌زمان

۲. نحوه ایجاد ترد در جاوا

در جاوا، دو روش اصلی برای ایجاد یک ترد وجود دارد:

۱. استفاده از کلاس Thread

class MyThread extends Thread {

public void run() {

for (int i = 1; i <= 5; i++) {

System.out.println("Thread: " + Thread.currentThread().getName() + " - Count: " + i);

try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }

}

}

public static void main(String[] args) {

MyThread t1 = new MyThread();

MyThread t2 = new MyThread();

t1.start();

t2.start();

}

}

✅در این روش، کلاس MyThread از Thread ارث‌بری کرده و متد run() را پیاده‌سازی می‌کند. سپس با متد start() ترد اجرا می‌شود.

۲. استفاده از اینترفیس Runnable

class MyRunnable implements Runnable {

public void run() {

for (int i = 1; i <= 5; i++) {

System.out.println("Runnable Thread: " + Thread.currentThread().getName() + " - Count: " + i);

try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }

}

}

public static void main(String[] args) {

Thread t1 = new Thread(new MyRunnable());

Thread t2 = new Thread(new MyRunnable());

t1.start();

t2.start();

}

}

✅ این روش برای پیاده‌سازی چندکلاسه و جلوگیری از محدودیت ارث‌بری در جاوا بهتر است.

۳. مدیریت تردها در جاوا

۱. همگام‌سازی تردها (Synchronization)

در برنامه‌های چندنخی، وقتی چندین ترد به یک منبع مشترک دسترسی دارند، باید از Synchronization استفاده کنیم.

class Counter {

private int count = 0;

public synchronized void increment() {

count++;

}

public int getCount() {

return count;

}

}


public class SyncExample {

public static void main(String[] args) throws InterruptedException {

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();

t1.join();

t2.join();


System.out.println("Final Count: " + counter.getCount());

}

}


کلمه کلیدی synchronized باعث می‌شود دو ترد هم‌زمان به متد increment() دسترسی نداشته باشند و از شرایط رقابتی (Race Condition) جلوگیری شود.

✅ متد join تضمین میکند که برنامه،قبل از نمایش نتیجه،منتظر پایان تردها بماند.

اگر syncronized حذف شود،شرایط رقابتی پیش میاد و مقدار count نادرست خواهد بود.

۴. تفاوت Thread و Runnable

روش پیاده‌سازی : ارث‌بری از کلاس Thread وپیاده‌سازی اینترفیس Runnable

محدودیت ارث‌بری : در استفاده از کلاس Thread فقط از Thread ارث می‌برد،در استفاده از Runnable می‌توان از چند کلاس ارث‌بری کرد

قابلیت استفاده مجدد: در استفاده از کلاس Thread کمتر،در استفاده از Runnable بیشتر

عملکرد در پردازش‌ها: در استفاده از کلاس Thread کم،در استفاده از Runnable بهینه تر

توصیه: اگر کلاس شما از قبل از کلاس دیگری ارث‌بری کرده است، بهتر است از Runnable استفاده کنید.

۵. مدیریت پیشرفته تردها با ExecutorService

در جاوا، استفاده از ExecutorService برای مدیریت تردها توصیه می‌شود:

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

public class ExecutorExample {

public static void main(String[] args) {

ExecutorService executor = Executors.newFixedThreadPool(3);

for (int i = 1; i <= 5; i++) {

int task = i;

executor.submit(() -> {

System.out.println("Executing Task: " + task + " - Thread: " + Thread.currentThread().getName());

});

}


executor.shutdown();

}

}

✅ این روش باعث مدیریت بهینه منابع و افزایش عملکرد برنامه می‌شود.

✅ در این کد، 5 تسک با 3 ، thread انجام میشود.

✅ متد submit برای ارسال تسک به threadpool، انجام میشود.

✅ پس از ارسال همه تسک‌ها، متد shutdown() برای بستن ExecutorService و آزادسازی منابع استفاده می‌شود. این متد تضمین می‌کند که هیچ تسک جدیدی به ThreadPool اضافه نمی‌شود، ولی تسک‌های در حال اجرا تمام خواهند شد.

📌 مزایای استفاده از ExecutorService

  1. مدیریت ساده‌تر تردها: نیازی به مدیریت دستی تردها ندارید.
  2. کنترل بهتر منابع: با استفاده از ExecutorService می‌توانید تعداد تردها را محدود کنید و منابع را بهینه‌سازی کنید.
  3. بهبود کارایی: از آنجا که تردها از قبل ایجاد شده‌اند، به جای ایجاد ترد جدید برای هر تسک، از تردهای موجود استفاده می‌شود که باعث افزایش کارایی می‌شود.

✅ اگر در برنامه‌ای چند تردی دارید که با داده‌های مشترک کار می‌کند، نیاز به همگام‌سازی (synchronization) خواهید داشت. در این کد خاص، چون تردها فقط عملیات مستقل چاپ انجام می‌دهند و به داده‌های مشترک دسترسی ندارند، synchronized لازم نیست:

public class ExecutorExample {

private static int counter = 0;

public static void main(String[] args) {

ExecutorService executor = Executors.newFixedThreadPool(3);


for (int i = 1; i <= 5; i++) {

executor.submit(() -> {

synchronized (ExecutorExample.class) { // Synchronizing access to the shared variable

counter++;

System.out.println("Executing Task: " + counter + " - Thread: " + Thread.currentThread().getName());

}

});

}


executor.shutdown();

}

}

✅ در اینجا، از synchronized برای همگام‌سازی دسترسی به متغیر counter استفاده شده است تا مقدار آن به طور ایمن توسط چند ترد تغییر یابد.

نتیجه‌گیری

🔹 مالتی تردینگ در جاوا به برنامه اجازه می‌دهد تا وظایف مختلف را هم‌زمان اجرا کند.
🔹 دو روش اصلی برای ایجاد ترد وجود دارد: ارث‌بری از Thread و پیاده‌سازی Runnable.
🔹 استفاده از Synchronization برای جلوگیری از تداخل تردها ضروری است.
🔹 برای مدیریت بهتر، می‌توان از ExecutorService استفاده کرد.


جاواmultithreadingآموزش برنامه نویسیبرنامه نویسی
برنامه نویس جاوا هستم،سعی میکنم پستهایی بگذارم که مفید و قابل استفاده باشه
شاید از این پست‌ها خوشتان بیاید