دوره‌ها / JAVA / تردها/نخ‌ها (Java Threads)

تردها/نخ‌ها (Java Threads)

15 دقیقه Article

نخ‌ها (Threads): اجرایِ موازی و چندوظیفگی 🧵🎢

خوش‌آمدید به دنیایِ پیچیده و جذابِ Multi-threading! نخ‌ها به برنامه‌یِ شما اجازه می‌دهند چندین کار را "به صورتِ همزمان" انجام دهید. مثلاً در حالی که برنامه در حالِ دانلودِ یک فایل است، کاربر همچنان بتواند رویِ دکمه‌ها کلیک کند.

۱. دو راه برایِ ساختِ نخ

  1. ارث‌بری از Thread: راحت است اما چون یک وراثت مصرف می‌شود، محدودیت ایجاد می‌کند.
  2. پیاده‌سازی Runnable: راهِ استاندارد و حرفه‌ای است.
{code_block('public class MyThread extends Thread {\n public void run() { System.out.println("Running!"); }\n}')}

۲. اجرایِ نخ 🚀

بسیار مهم: برایِ اجرایِ همزمان، نباید متدِ run() را صدا بزنید! باید متدِ start() را صدا بزنید تا سیستم‌عامل یک نخِ جدید ایجاد کند.

{code_block('MyThread thread = new MyThread();\nthread.start();')}

۳. چالش‌هایِ نخ‌ها: رقابت (Race Condition)

وقتی دو نخ همزمان سعی کنند یک متغیرِ مشترک را تغییر دهند، فاجعه رخ می‌دهد. برایِ حل این مشکل از کلمه‌یِ کلیدی synchronized استفاده می‌کنیم تا در هر لحظه فقط یک نخ اجازه دسترسی داشته باشد.

اصطلاحات: - Concurrent: اجرایِ چندین کار به صورتِ اشتراکِ زمانی (تویِ صف رفتن). - Parallel: اجرایِ واقعیِ همزمان رویِ پردازنده‌هایِ چند هسته‌ای.

Thread.sleep:

گاهی برایِ شبیه‌سازیِ کارهایِ زمان‌بر یا ایجادِ وقفه، از Thread.sleep(1000) استفاده می‌کنیم. دقت کنید که این متد نیاز به try-catch دارد.

نکته پیشرفته: امروزه در ابعادِ بزرگ، به جایِ کارِ مستقیم با Thread، از ExecutorService و ThreadPools استفاده می‌کنیم که مدیریتِ نخ‌ها را بسیار هوشمندانه‌تر انجام می‌دهند.
<hr style="margin: 50px 0; border: 0; border-top: 1px dashed rgba(255,255,255,0.1);">

بخش تخصصی: مهندسی پیشرفته و امنیت سیستم 🛡️⚙️

در این بخش، به مفاهیمی می‌پردازیم که برای پایداری و امنیتِ برنامه‌های بزرگِ جاوا حیاتی هستند.

۱. استراتژی مدیریت استثناها (Fail-Fast vs Fail-Safe)

در طراحی سیستم‌های بزرگ، ما معمولاً از الگوی Fail-Fast استفاده می‌کنیم؛ یعنی به محض وقوع خطا، برنامه را با یک استثنای دقیق متوقف می‌کنیم تا از انتشار فساد داده‌ها جلوگیری کنیم. همچنین، نباید استثناها را با یک بلاکِ catch خالی "خفه" کنید. هر استثنا باید حتماً لاگ (Log) شود یا به لایه‌ی بالاتر گزارش داده شود.

۲. کالبدشکافی Autoboxing در حافظه

تبدیلِ اتوماتیکِ انواعِ Primitive به اشیاءِ Wrapper (مثل تبدیل int به Integer) در ظاهر ساده است، اما در حلقه‌هایِ سنگین می‌تواند باعثِ ایجادِ هزاران شیءِ اضافه در حافظه Heap و در نتیجه فشار به Garbage Collector شود. همیشه در بخش‌های حساس به پرفورمنس، از انواع Primitive استفاده کنید.

۳. پارادایم برنامه‌نویسی تابعی (Functional Programming)

استفاده از Lambda Expressions شروعِ حرکتِ جاوا به سمت برنامه‌نویسی تابعی بود. این سبک نه تنها باعثِ کوتاه‌تر شدنِ کدها می‌شود، بلکه امکانِ اجرایِ موازیِ کدها (Parallel processing) را روی پردازنده‌های چند هسته‌ای بسیار ساده‌تر می‌کند.

نکته پایانی: مهارت در مدیریتِ خطاها و استفاده از نخ‌ها (Threads)، مرزِ بین یک کدنِویسِ مبتدی و یک توسعه‌دهنده‌یِ ارشد است. همیشه کدی بنویسید که در مقابلِ بدترین ورودی‌ها هم مقاوم باشد.

تمرین‌های عملی

برای تثبیت یادگیری این درس تمرین‌های زیر را حل کنید

ساخت Thread ساده Medium
سوال تمرین

یک کلاس به نام MyRunnable بنویسید که اینترفیس Runnable را پیاده‌سازی کند و در متدِ run کلمه‌یِ Hello را چاپ کند.

پاسخ تمرین
JAVA
class MyRunnable implements Runnable {
  @Override
  public void run() {
    System.out.println("Hello");
  }
}
public class Main {
  public static void main(String[] args) {
    Thread t = new Thread(new MyRunnable());
    t.start();
  }
}

آماده رفتن به درس بعدی هستید؟

این درس را به پایان رساندید و می‌توانید به درس بعدی بروید.