این
مقاله شرح میدهد چگونه Thread
ها در
برنامه نویسی جاوا ایفای نقش می کنند.
قبل از
کنکاش در جزییات جاوا یک نگاه عمومی به
thread ها
مورد نیاز است.
به
تعبیر ساده ، یک thread
مسیر
اجرای یک برنامه میباشد.
امروزه
بیشتر برنامههای نوشته شده مانند یک تک
thread
اجرا
میشوند ، مسأله ای را فرض کنید باید در
یک زمان چندین رویداد یا کنش اتفاق بیفتند.
اجازه
دهید بگوییم برای مثال، یک برنامه قادر
نیست یک عکس را بکشد مادامیکه در حال
خواندن اطلاعات ارسال شده از صفحهکلید
است .
این
برنامه باید تمام توجه خود را معطوف به
خواندن اطلاعات ارسال شده از صفحهکلید
نماید و فاقد توانای برای کنترل بیش از
یک رویداد در یک زمان می باشد.راه
حل ایدهآل برای این مشکل اجرای یکپارچه
ی دو بخش یا بیشتر، از یک نرمافزار در
یک زمان می باشد.
Thread ها
به ما این اجازه را می دهند.
نرمافزار
های چند Thread
همه ی
توان خود را انجام میدهند تا چندین
thread
همزمان
در یک تک برنامه اجرا شود.از
یک نگاه منطقی مالتی تریدینگ به معنای
این است که چندین خط از یک برنامه میتواند
در یک زمان اجرا شود، به هر حال، این بدان
معنی نیست که یک برنامه دو بار اجرا شود
و بگوییم چندین خط از برنامه وجود دارد
که در یک زمان اجرا شده است.
در این
حالت سیستم عامل با برنامه مثل دو فرایند
مجزا رفتار می کند.
در سیستم
عامل یونیکس انشعاب یک جریان یک زیر شاخه
با آدرس متفاوت برای هر دو کد و داده ایجاد
میکند.
به هر
حال ()fork
تعداد
زیادی overhead
برای
سیستم عامل میسازد، باعث تمرکز عملیات
بر روی cpu
می شود.
در عوض
با شروع thread
، یک
مسیر کار آمد برای اجرای برنامه ایجاد
شده مادامی که هنوز در محدوده ی دادههای
اصلی می باشد.
ایده ی
تسهیم محدوده ی دادهها ایده ی بسیار
مفیدی است، اما باعث برخی محدوده های به
هم مرتبط میشود که بعداً در باره ی آن
بحث خواهیم کرد.
ایجاد
thread ها
آفریننده
های جاوا دو روش دوست داشتنی برای خلق
thread ها
ایجاد کرده اند:
پیادهسازی
یک رابط
(Interface)و
توسعه ی یک کلاس.
توسعه
ی یک کلاس راهی است که جاوا، متد ها و
متغییر ها را از کلاسهای مادر به ارث می
برد. این
محدودیت در جاوا میتواند
بوسیله ی پیادهسازی رابط برطرف شود که
متداول ترین روش برای آفریدن thread
هاست.
( توجه
داشته باشید که عمل ارث بری فقط به کلاس
این اجازه را میدهد که همانند یک thread
اجرا
شود. آن
کلاس را شروع یا اجرا می کند.)
رابط
ها(Interfaces)
راهی را
برای برنامه نویس تدارک میبیند تا این
عمل را در زمینه یک کلاس قرار دهند.رابط
ها برای آنکه ملزومات پیادهسازی کلاسها
را طراحی کنند به کار میروند.
رابط
همه چیز را تنظیم می کند و کلاس یا کلاسها
یی که رابط ها را پیادهسازی میکنند
همه را به کار می اندازد.
تنظیمات
مختلف کلاسها که رابط ها را پیادهسازی
میکنند، همه و همه یک نقش را ایفا می
کنند.
تفاوتهایی
بین یک کلاس و یک رابط وجود دارد.
اول، یک
را بط میتواند فقط شامل متد های انتزاعی
(abstract)
و یا
متغییرهای پایانی پایا (
static final variables )یا
ثوابت باشند.
به عبارت
دیگر، کلاسها میتوانند متد ها را
پیادهسازی کنند و همچنین شامل متغییر
ها یی باشند که مقدار آنها ثابت نیست.
دوم، یک
رابط نمیتواند هر متدی را پیادهسازی
کند. یک
کلاسی که یک رابط را پیادهسازی میکند
باید همه ی متد های تعریف شده در آن رابط
را پیادهسازی کند.
یک رابط
توانایی آن را را دارد تا توسط دیگر رابط
ها توسعه داده شود و (بر
خلاف کلاس ها)
میتواند
توسط چندین رابط توسعه یابد.
از این
گذشته، یک رابط نمیتواند بوسیله ی یک
عملگر جدید تعریف شود، برای مثال:
Runnable
a=new Runnable();
مجاز
نیست
.
اولین
روش برای آفریدن یک
thread
بست
یک
thread
از
کلاس آن است
.
این
کار را فقط زمانی انجام دهید که کلاسی را
که میخواهید به شکل
thread
بست
دهید هرگز نیاز به بست آن کلاس به دیگر
کلاسها را نداشته باشید
.
این
کلاس در بسته ی
java.lang
تعریف
شده است که نیاز به وارد کردن این بسته
دارید بنا بر این کلاسهای ما از این
تعریف آگاه می شوند
.
import java.lang.*;
public class Counter extends Thread
{
public void run()
{
....
}
}
مثال
بالایک کلاس جدید به نام
Counter
ایجاد
میکند که کلاس
Thread
را
بسط میدهد و متد
Thread.run()
را
برای اجرای خود پیاده می کند
.
متد
run
جایی
به کار میرود که همه ی وظایف کلاس
Counter
انجام
شده باشد
.
import java.lang.*;
public class Counter implements Runnable
{
Thread T;
public void run()
{
....
}
}
در
اینجا متد
run
در
رابط
Runnable
تعریف
و پیادهسازی شده است
.
توجه
داشته باشید ما یک رابط از کلاس
Thread
همچون
یک متغییر از کلاس
Counter
داریم
.
تنها
تفاوت میان دو متد، پیادهسازی متد
Runnable
است،
این کار انعطاف بیشتری در ایجاد کلاس Counter
در
اختیار ما قرار می دهد
.
در
مثال بالا هنوز این فرصت وجود دارد که در
صورت لزوم کلاس
Counter،
بسط داده شود
.
بیشتر
کلاسهای ساخته شدهای که نیاز به اجرا
run
به
عنوان
thread
داشته
ًباشند ،
Runnable
را
پیاده ساری میکنند، از این رو آنها
برخی دیگر از وظایف کلاسهای دیگر را
احتمالاً بسط میدهند
.
گمان
نکنید که رابط
Runnable
هر
کار واقعی را زمانی که
Thread
اجرا
شده است انجام انجام میدهد
.
این
تنها کلاس آفریده شده ایست، تا ایده ای
برای طراحی کلاس
thread
باشد
.
در
حقیقت، این یک محتوی بسیار کوچک است فقط
یک متد انتزاعی
(abstract).
در
اینجا تعریف رابط
Runnable
مستقیماً
از منابع جاوا آمده است
.
package java.lang;
public interface Runnable {
public abstract void run();
}
این
همه ی آن چیزی است که رابط
Runnable
می
نامیم
.یک
رابط فقط طرحی که کدام کلاسها باید
پیادهسازی شوند را ارائه می کند
.
در
این حالت رابط
Runnable،فقط
بر روی متد
run
تمرکز
می کند
.
بنا
بر این، بیشتر کار در کلاس
thread
انجام
می شود
.
یک
نگاه نزدیک تر به یک بخش در تعریف کلاس
thread
این
ایده رابه ما میدهد که چه چیز واقعاً در
حال انجام است
:
public class Thread implements Runnable {
...
public void run() {
if (target != null) {
target.run();
}
}
...
}
از کد بالا این مطلب آشکار است که کلاس thread همچنین رابط Runnable را پیادهسازی می کند.
Thread.run چک میکند تا اطمینان یابد هدف کلاس ( کلاسی که میرود تا همانند یک thread اجرا شود)
پوچ نیست، و سپس متد run به عنوان هدف اجرا می شود. زمانی که این اتفاق بیفتد متد run هدف همانند thread خود
اجرا خواهد شد.
شروع و پایان
از آنجایی که روشهای مختلفی برای ایجاد یک نمونه از thread در حال حاضر ارائه شده ، ما بحث خواهیم کرد که پیادهسازی
یک thread ها با روشهای در دسترس برای شروع و پایان آنها با استفاده از یک اپلت کوچک شامل یک thread برای
نمایش مکانیک:
مثال و کد: CounterThread
اپلت بالا شمارش را از صفر شروع خواهد کرد و خروجی را در یک پنجره و در یک کنسول هردو به نمایش در خواهد آورد.
یک نگاه اجمالی این احساس را به ما میدهد که برنامه شمارش را شروع خواهد کرد و هر عدد را نمایش خواهد داد، اما این همه
چیز نیست. یک نگاه دقیقتر به اجرای این اپلت هویت ,واقعی آن را آشکار خواهد کرد.