نحوه ی ایجاد یک ترد در زبان برنامه نویسی جاوا


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

- روش اول: به این صورت است که کلاسی ایجاد کرده سپس آن کلاس ویژگی های خود را از کلاس Thread جاوا به ارث ببرد. 
- روش دوم: به این صورت است که کلاسی ایجاد کرده و آن کلاس به اجرای یک اینترفیس تحت عنوان Runnable بپردازد (لازم به ذکر است کلاسی که اقدام به اجرای Runnable نماید بدون آن که خصوصیتی را از کلاس Thread به ارث ببرد، خواهد توانست اقدام به ساخت یک Thread نماید.)

در ادامه آموزش، هر دو روش را مورد بررسی دقیق قرار خواهیم داد. برای شروع یک پروژه جدید تحت عنوان Thread ایجاد کرده و کلاسی در آن تحت عنوان ThreadA ایجاد می کنیم:

public class ThreadA extends Thread {

}

همان طور که در کد فوق مشاهده می شود، کلاسی که تحت عنوان ThreadA ایجاد کردیم کلیه خصوصیات، ویژگی ها و متدهای کلاس Thread جاوا را به ارث خواهد برد. حال کد فوق را به صورت زیر تکمیل می کنیم:

public class ThreadA extends Thread {
    @Override
    public void run() {
        System.out.println("Thread A");
        for (int i = 1; i <= 5; i++) {
            System.out.println("From thread A loop no= " + i);
        }
    }
}

می بینیم که ابتدا متدی تحت عنوان run را وارد برنامه خود کرده ایم. لازم به ذکر است زمانی که یک کلاس از کلاس Thread ارث بری می کند می بایست این متد را Override کرد که در غیر این صورت اکلیپس دوره واژه run را نقطه چین قرار خواهد داد و چنانچه نشانگر موس خود را روی نقطه چین قرار دهیم، اکلیپس به ما پیشنهاد می دهد که این متد را Override کنیم.

حال از آنجا که قصد داریم علاوه بر کلاسی تحت عنوان ThreadA کلاس دیگری تحت عنوان ThreadB نیز ایجاد کنیم، در متد run دستوری را می نویسیم مبنی بر این که عبارت Thread A را در پنجره کنسول به نمایش در آورد تا بدانیم که خروجی برنامه متعلق به کدام Thread است. در ادامه یک لوپ یا حلقه از جنس for تعریف می کنیم. در واقع هر کاری که بخواهیم Thread ما انجام دهد می بایست داخل متد run نوشته شود.

متغیری از جنس int تحت عنوان i ایجاد می کنیم به این شکل که نقطه شروع لوپ عدد 1 خواهد بود، نقطه پایان لوپ کوچکتر یا برابر با 5 و در هر بار لوپ شدن، یک واحد به متغیر i اضافه خواهد شد. سپس داخل for دستور ;()System.out.println را نوشته سپس داخل پرانتز متد println عبارت :From Thread A loop no را می نویسیم که حاکی از آن است که «از Thread A به همراه لوپ شماره:» را در پنجره کنسول به نمایش در آورد. سپس یک علامت + قرار داده و نام متغیری که داخل for ایجاد کردیم را می نویسیم. اکنون کلاس دیگری تحت عنوان ThreadB ایجاد کرده و آن را به شکل زیر تکمیل می کنیم:

public class ThreadB extends Thread {
    @Override
    public void run() {
        System.out.println("Thread B");
        for (int i = 1; i <= 5; i++) {
            System.out.println("From thread B: loop no = " + i);
        }
    }
}

همان طور که ملاحظه می شود این کلاس نیز از کلاس Thread ارث بری می کند و تنها تفاوتی که با کلاس ThreadA دارد این است که هر کجا که حرف A داشتیم به حرف B تغییر یافته است. مجدد اقدام به ایجاد کلاس دیگری تحت عنوان ActionClass می نماییم و به خاطر داشته باشیم که در حین ساخت این کلاس حتماً گزینه public static void main را تیک بزنیم چرا که این کلاس به منزله نقطه شروع برنامه ما خواهد بود:

public class ActionClass {
    public static void main(String args[]) {
    }
}

نیاز است تا از روی هر کدام از کلاس های ThreadA و ThreadB یک آبجکت ایجاد کنیم. برای این منظور کد فوق را به صورت زیر تکمیل می کنیم:

public class ActionClass {
    public static void main(String args[]) {
        ThreadA a = new ThreadA();
        ThreadB b = new ThreadB();
    }
}

همان گونه که در آموزش های پیشین توضیح داده شد، ابتدا نام کلاس مد نظر را نوشته سپس نامی برای آبجکتی که می خواهیم از روی آن کلاس ایجاد کنیم در نظر می گیریم. سپس یک علامت مساوی قرار داده و از آنجا که می خواهیم یک آبجکت جدید ایجاد کنیم می بایست از کلید واژه ی new استفاده نماییم. سپس مجدد نام کلاس مد نظر را نوشته و یک علامت ;() پس از آن قرار می دهیم.

اکنون برای آن که بتوانیم آبجکت های ساخته شده از روی کلاس Thread را اجرا نماییم نیاز به متدی تحت عنوان start داریم. برای این منظور همان طور که در کد زیر مشخص است متد start را به آبجکت های ساخته شده از روی کلاس های ThreadA و ThreadB ضمیمه می کنیم:

public class ActionClass {
    public static void main(String args[]) {
        ThreadA a = new ThreadA();
        a.start();
        ThreadB b = new ThreadB();
        b.start();
    }
}

به طور خلاصه آبجکت ساخته شده از روی کلاس ThreadA نامش a است و آبجکت ساخته شده از روی کلاس ThreadB نامش b است. حال متد start را به هر دوی این آبجکت ها ضمیمه می کنیم. اکنون اگر برنامه خود را اجرا کنیم با خروجی زیر مواجه خواهیم شد:

همان طور که در اجرای فوق می بینیم اول Thread مرتبط با کلاس ThreadB اجرا شده است سپس Thread مرتبط با کلاس ThreadA. برای دومین بار برنامه را اجرا می کنیم:

می بینیم که این بار ترتیب اجرای Thread ها عکس اجرای قبل است. در حقیقت علت این مسئله از آنجا ناشی می شود که در یک برنامه جاوا، تردها نه تنها به صورت هم زمان اجرای می شوند بلکه این در حالی است که هر دو ترد مستقل از یکدیگر اجرا می شوند و به همین دلیل نیز می باشد که هر کدام ابتدا شانس اجرا شدن را پیدا کند، اول اجرا خواهد شد. حال فرض کنیم که می خواهیم یک ترد به روش دومی که در بالا به آن اشاره شد ایجاد کنیم. برای این منظور پروژه دیگری تحت عنوان Runnable ایجاد کرده و کلاسی در آن به نام MyThread ایجاد می کنیم:

public class MyThread {

}

به طور خلاصه می توان گفت که در این روش به منظور ایجاد یک ترد، از اینترفیسی یی تحت عنوان Runnable استفاده خواهیم کرد. در واقع، وظیفه ای که این اینترفیس بر عهده دارد این است که چنانچه کلاسی این اینترفیس را اجرا کند، آن کلاس بدون آن که چیزی را از کلاس Thread جاوا به ارث ببرد این امکان را خواهد داشت تا یک ترد ایجاد نماید. حال که با وظیفه Runnable بیشتر آشنا شدیم، نیاز است تا کد فوق را به صورت زیر تکمیل کنیم:

public class MyThread implements Runnable {
    @Override
    public void run() {
        for (int i = 1; i <= 5; i++) {
            System.out.println("From My Thread loop no:" + i);
        }
    }
}

ابتدا کلاس MyThread، با استفاده از کلید واژه implements اقدام به اجرای Runnable خواهد کرد. سپس متد مرتبط با ایجاد یک ترد که run نام دارد را وارد برنامه خود می کنیم (به خاطر داشته باشیم برای آن که بتوانیم از این متد استفاده کنیم، می بایست آن را Override کنیم.) سپس همانند تردهای قبلی، یک لوپ از جنس for ایجاد کرده و کدهای قبلی را برای آن در نظر می گیریم. در این مرحله از کار نیاز است تا کلاس دیگری تحت عنوان ActionClass ایجاد کنیم که به منزله نقطه شروع برنامه ما خواهد بود (به خاطر داشته باشیم که گزینه public static void main را تیک دار نماییم):

public class ActionClass {
    public static void main(String[] args) {
    }
}

در ادامه بایستی یک آبجکت از روی کلاسی که تحت عنوان MyThread ایجاد کردیم در این کلاس ایجاد نماییم. برای این منظور کد فوق را به صورت زیر تکمیل می کنیم:

public class ActionClass {
    public static void main(String[] args) {
        MyThread test = new MyThread();
    }
}

نام آبجکتی که از روی کلاس MyThread ایجاد کرده ایم test است. اگر خاطرمان باشد در روش اول ساخت یک ترد، نام آبجکت ساخته شده از روی کلاس خود را مستقیماً به متد start ضمیمه می کردیم و ترد ما اجرا می شد اما این در حالی است که زماین که از Runnable برای ایجاد یک ترد استفاده می کنیم، می بایست آبجکتی از روی کلاس Thread نیز ایجاد کرده، آن آبجکت را به آبجکتی که از روی کلاس خود ساختیم مرتبط ساخته و در نهایت آبجکت ساخته شده از روی کلاس Thread را به متد start ضمیمه کنیم. برای این منظور کد فوق را به صورت زیر تکمیل می کنیم:

public class ActionClass {
    public static void main(String[] args) {
        MyThread test = new MyThread();
        Thread thread = new Thread(test);
        thread.start();
    }
}

همان طور که ملاحظه می شود، یک آبجکت از روی کلاس Thread جاوا تحت عنوان thread ایجاد کرده ایم (اگر توجه کنیم می بینیم که آبجکت ساخته شده از روی کلاس Thread با حرف کوچک نوشته شده است. به جای این نام می توانیم از هر نام دیگری نیز استفاده کنیم.) سپس داخل پرانتز مرتبط با کلاس Thread نام آبجکتی تحت عنوان test که از روی کلاس MyThread ایجاد کردیم را نوشته و در نهایت آبجکت thread را به متد start که وظیفه دارد یک ترد را ایجاد کند ضمیمه می کنیم. اگر برنامه خود را اجرا کنیم با خروجی زیر مواجه خواهیم شد:

شاید مطالب این آموزش تا حدودی سخت به و غیر قابل فهم به نظر برسند، اما این در حالی است که با تکرار و تمرین و استفاده از تردها و اینترفیس ها در پروژه های واقعی، این مفاهیم بیشتر درک خواهند شد.

دانلود فایل‌های تمرین
لیست نظرات
کاربر میهمان
دیدگاه شما چیست؟
کاربر میهمان
ashkan
ashkan
با این‌که ‌همه آموزش هارو‌سریع فهمیدم. این آموزش رو به کلی نفهمیدم. اگر روش اول و دوم و جداگونه از اول با توضیحات پایه ای میومدید جلو بهتر بود. اصلا هیچی‌متوجه نشدم
کاربر میهمان
کاربر میهمان
بسیار عالی و روان و دقیق. خدا خیرت بده داداش.
کاربر میهمان
کاربر میهمان
آموزشاتون فوق العاده و روانه
ممنون بابت تمامي زحماتتون
کاربر میهمان
کاربر میهمان
سلام . ممنون بابت اموزشتون . میخواستم بگم تو روش اول شما متدهایی با نام run ایجاد کردید بعد موقع شی سازی یا ابجکت ساختن اسم a و b رو با ()start نوشتید نباید اینجا از ()run استفاده میکردیم .
کاربر میهمان
کاربر میهمان
مثا اینکه بعضی از دوستان به اشتباه ایراد گرفتن و متوجه نشدن اون کلاس AوB به روش ارث بری از کلاس ترد و به روش اول ساخت ترد نام گذاری شدن و اصلا به My Thread ربطی ندارن کلاس My Thread به روش دوم یعنی Runnable ساخته شده و اصلا ربطی به اون دوتا کلاس اول نداره
کاربر میهمان
کاربر میهمان
ممنون بایت زحماتتون
کاربر میهمان
کاربر میهمان
آقا به ما بگو فرق استفاده از اینترفیس Runnable با ارث بری از کلاس ترد چیه
کاربر میهمان
کاربر میهمان
متوجه اشتباهم شدم..کلاس ترد از کلاسهای خود جاواست
کاربر میهمان
کاربر میهمان
ببخشید به نظر شما این اموزش ناقص نیست در اول اموزشpublic class ThreadA extends Thread بیان کردیدو هیچ کجا از محتوای کلاس Thread که چیست بیان نشده من اموزشهاتون مرحله به مرحله دنبال کردم لطفا اگر اشتباه میکنم راهنمایی کنید
محمدتقی کاوسی
محمدتقی کاوسی
عاقا اینترفیس Runnable نیاز به تعریف نداره؟ آیا این اسم کلیدی جاوا هست یا میشه هر اسم دیگه ای استفاده کرد؟
کاربر میهمان
کاربر میهمان
با تشکر از اموزش های قبلی و زحماتتون من سه تا انتقاد داشتم از این اموزشتون 1.گنگ گفتین البته فقط این اموزش میگم2.سریع رفتین و فک کنم چون خواستین هر دو روش در یک بخش توضیح بدین اینطور شده3.بدون ویرایش هست که باعث سختتر شدن درک میشه. و در آخر بازم ممنون بابت زحمات!
عیسی پور
عیسی پور
ممنون از آموزش خوبتون
در ابتدای این آموزش بعد از ایجاد پروژه 53 ام فرمودید کلاسی تحت عنوان MyThread باید ایجاد کنیم که صحیحش "ThreadA " باید باشه.
Sina Deuxshiri
Sina Deuxshiri
سلام
لطفا در مورد نام گذاری کلاس ها، متغیر ها و متد ها در جاوا مطالعه کنید. این چیزی که شما فرمودین اصلا صحیح نیست.

در پاسخ به

عیسی پور
عیسی پور
آقای دوشیری جهشی به این آموزش نیومدم از اول پیگیر بودم شما منظور منو نگرفتی منظورم این بود اشتباه نوشته شده MyThread در حالی که تو تصویری که از کد گذاشتن اسم کلاس ThreadA هست.

در پاسخ به

Sina Deuxshiri
Sina Deuxshiri
من دقیقا نمی دونم کجا رو میگین. اگه مطمئن هستین دقیق تر بگین تا تصحیح شه. ممنون.

در پاسخ به

عیسی پور
عیسی پور
http://goo.gl/VpHTO5

در پاسخ به

Sina Deuxshiri
Sina Deuxshiri
دوست عزیز متوجه شدم. شما اشتباه می کنید. ببینید کلاسی که اسمش MyThread هست، یه کلاس جدیدی هست که مدرس به غیر از دو کلاس قبلی ایجاد کرده. در این کلاس اینترفیس Runnnable پیاده سازی شده.

در پاسخ به

m.ali
m.ali
سلام. کلیت ایرادی که گرفتند درست است. (هرچند بنظر در لینک ارسالی، به اشتباه قسمت مورد دار را نمایش داده اند.)
در جمله آخر سطر چهارم آموزش نوشته شده:
"برای شروع یک پروژه جدید تحت عنوان Thread ایجاد کرده و کلاسی در آن تحت عنوان «««MyThread»»» ایجاد می کنیم:"
درحالیکه در ذیل آن، در باکس مشکی مربوط به نمایش کد ها (اولین باکس مشکی این آموزش) آمده:
"public class «««ThreadA»»» extends Thread"
فکر کنم ایراد ایشان به این قسمت باشد.
این ویرایش ها برای هر چه بی نقص تر کردن این مجموعه آموزش های بسیار زیبا و با ارزش سکان آکادمیست. و تا الان هم توجه و نقدپذیری سکان تحسین برانگیز بوده است!

در پاسخ به

کاربر میهمان
کاربر میهمان
سلام. اول تشکر میکنم به خاطر آموزش بسیار عالی و بسیار روانی که ارائه داده اید.
سوالی که دارم در مورد @Override می باشد. من طبق دستورات شما اقدام به ایجاد Thread کردم ولی خطايي و یا پيغامی مبنی بر نیاز داشتن به @Override را به من نشان نداد و برنامه به درستي اجرا شد!
میخواستم بدون این عدم نیاز به @Override علت خاصی دارد ؟ یا اینکه این دستور optional است؟
با تشکر از شما
Sina Deuxshiri
Sina Deuxshiri
سلام.
Override@ دستور نیست. انوتیشن هست. در مورد انوتیشن ها سرچ کنید متوجه میشید.

در پاسخ به

علیرضا
علیرضا
من دقت کردم شما در تمام نظرات میگید که برید سرچ کنید. ممنون از اینکه گوگل رو به ما معرفی کردین :) لطفا اگه پاسخ رو نمیدونین اسپم نکنید

در پاسخ به

Sina Deuxshiri
Sina Deuxshiri
سلام. دوست عزیز مطمئن باشید که من مفهوم انوتیشن و می‌دونم چیه، و اگر نمی‌دونستم، اصلا نمی‌دونستم که اسمش چیه. اینکه میگم سرچ کنید چند تا دلیل داره. ابتدا اینکه برای یادگیری باید خودتون پی‌گیر باشید، اینکه بخواین همش از این و اون سوال بپرسید و منتظر بشید تا راهنماییتون کنه، به جایی نمی‌رسین. دوم اینکه برای توضیح انوتیشن تقریبا یک مطلب آموزشی نیاز هست که توضیح بدیم که چی هست!!! مسلما در چند خط کامنت نمیشه توضیح داد. موفق باشید :)

در پاسخ به

bijan9
bijan9
that was perfect . thank you.
بهزاد مرادی
بهزاد مرادی
That`s very kind of you dude. You`re welcome

در پاسخ به

mohammadnaxx
mohammadnaxx
farsi ra pas bedarim !!!!!!!!!!

در پاسخ به