جاوا و تکنولوژی های آن

java programming language

در این وبلاگ به بررسی نکات موجود در جاوا و تکنولوژی های آن می پردازیم

طبقه بندی موضوعی
مفهوم Multithread : در یک پروسس بتوان بخش های مختلف برنامه را بصورت همزمان اجرا کرد

Thread of execution : هر جریان اجرایی را یک thread of execution میگویند 

Parallel processing : در پردازنده های بالای یک هسته میتوانیم چند بخش از برنامه را واقعا و در یک لحظه اتمیک بصورت موازی اجرا کنیم هر اجرای موازی یک اجرا Concurrent هم محسوب میشود ولی نه برعکس

Concurrency : به اجرای همزمان چند بخش همروندی یا concurrency گفته میشود که لزوما این پردازش ها بصورت Parallel اجرا نمیشوند مثلا میتواند در یک هسته از پردازنده اتفاق بیوفتد به این شکل که جریان اجرایی تا یک مرحله انجام میشود و بعد جریان اجرایی دیگری انجام میشود و در هر لحظه اتمیک میتوان دید که فقط یک Thread در حال اجرا هستند لذا در پردازنده هایی با تعداد هسته کم اگر از Multithread استفاده کنیم ممکن است با کاهش Performance روبرو بشویم ولی داشتن خاصیت هم روندی در برنامه مفید است

برای ایجاد ترد در جاوا دو راه وجود دارد یکی ارث بری از کلاس Thread و یا پیاده سازی کلاس Runnable حال کدامیک بهتر است ؟

وقتی کلاس ما از Thread ارث بری میکند موقع اجرا تنها با فراخوانی متد start کد اجرا میشود و پیاده سازی راحتی دارد ولی مشکلی که وجود دارد چون در جاوا multi inheritance نداریم امکان اینکه کلاس ما از کلاس دیگری ارث بری بکند وجود نخواهد داشت 

وقتی کلاس ما کلاس Runnable را پیاده سازی میکند بعدا باید آنرا توسط یک ابجکت جدید Thread در یک ترد جدید اجرا کنیم که خب پیاده سازی را کمی بیشتر میکند ولی چون Runnable یک اینترفیس است کلاس ما آزاد است که از هر کلاس دیگری ارث بری داشته باشد

وقتی thread ای ایجاد شد میتوانیم از طریق متد start آنرا اجرا کنیم سوال اینجاست که فراخوانی متد run هم برنامه را اجرا میکند آیا با فراخوانی متد run واقعا یک ترد جدید ایجاد میشود ؟
با فراخوانی متد start واقعا از سیستم عامل یک ترد جدید گرفته میشود و کد در آن ترد اجرا میشود ولی با فراخوانی run ترد جدیدی ایجاد نمیشود و فقط بصورت method invocation متد run را فراخوانی کرده ایم و برنامه در تردی که متد run را فراخوانی کرده است اجرا میشود 

گرفتن ترد جاری : با استفاده از ()Thread thread = Thread.currentThread میتوان به ترد جاری دست پیدا کرد 

join کردن : گاهی لازم است کار یک ترد تمام شود تا اجرای بخش دیگری ادامه پیدا کند با متد join میتوانیم ترد را به حالت موقتی متوقف کنیم تا کار ترد دیگری انجام شود و بعد ادامه اجرای برنامه را برویم 
متد های join و sleep میتوانند خطای InterruptedException تولید کنند

priority : ما میتوانیم اولیت اجرای یک ترد را با setPriority مشخص کنیم و عددی بین 1 تا 10 ارسال کنیم هر چه عدد به 10 نزدیک تر باشد الویت اجرا بالاتری را دارد ولی تضمینی وجود ندارد و این بر عهده سیستم عامل است که طبق الویتی که ما مشخص کردیم آن ترد را با الویت بیشتری اجرا کند یا نه . در حالت عادی همه ترد ها الویت 5 دارند

Daemon Thread : ترد شبح نوع خاصی از ترد ها هستند که در پس زمینه اجرا میشوند و معمولا خودشان مستقلا کار خاصی انجام نمیدهند و کارشان انجام خدماتی به ترد های دیگر است مثلا Garbage Collector خود یک Daemon Thread است ما متوانیم با متد setDaemon مشخص کنیم که این ترد از نوع شبح باشد . چنانچه اجرای تمامی ترد ها به اتمام رسیده باشد JVM اجرای Daemon Thread ها را هم خودکار خاتمه میدهد

همه ترد ها از حافظه Heap بطور مشترک استفاده میکنند ولی هر کدام حافظه Stack اختصاصی خودشان را دارند برای همین موقع Debug کردن باید به این نکته دقت داشت و همین متفاوت بودن Stack ها دیباگ کردن را مشکل تر میکند

Shared Resource : یک موجودیتی (متغییر ، فایل ، ابجکت و ...) که همزمان در چند ترد مورد استفاده قرار میگیرد

Race Condition : شرایطی است که چند ترد میخواهند به یک Shared Resource دسترسی پیدا کنند و حداقل یکی از ترد ها سعی کند تغییری در منبع ایجاد کند 
 
critical section : اینکه چند ترد میتوانند از یک شی مشترک استفاده کنند مشکلاتی را هم ایجاد میکند:
به طور مثال دو ترد در حال تغییر دادن یا خواندن یک شی باشند 
یا یک ترد شروع کند درون یک فایل محتویاتی را بنویسد و ترد دیگر آن فایل را ببندد 
به این حالت ها که Race Condition بوجود می آید critical section میگوییم حالتی است که نمیخواهیم توسط چند ترد همزمان اجرا شوند

Mutual Exclusion یا Mutex : انحصار متقابل یعنی چند ترد نباید بخش critical section خود را اجرا بکنند و با ورود یک ترد به بخش بحرانی باید از ورود بقیه ترد ها جلوگیری شود 

Synchronized : جاوا برای پیاده سازی Mutex از کلمه کلیدی Synchronized استفاده میکند و هر نخ هنگام ورود به یک Critical Section یک قفل (Lock) را در اختیار میگیرد و هنگام خروج آن قفل آزاد میشود و اینطوری Shared Resource ما محافظت میشود 

برای روشن شدن مفهوم Synchronized به مثال زیر دقت کنید 

public class BnakAccount {
private int balance;
public synchronized void withdraw (int amount){
     balance -= amount;
}
public synchronized void deposit (int amount){
     balance += amount;
}
}
در این کلاس موجودی یک حساب بانکی نگهداری میشود فرض کنید این کلاس توسط ترد های گوناگونی مورد استفاده قرار میگیرد و همینطور نباید موقعی که وجهی به حساب اضافه میشود وجهی از آن کم شود (deposit و withdraw) و باید در هر لحظه یک عملیات توسط یک ترد انجام شود ولی اگر از کلاس BankAccount یک ابجکت دیگری ساخته بودیم شرایط در ان ابجکت اعمال میشود و synchronized در سطح instance اعمال میشود 
وقتی ما متدی بصورت synchronized داریم قفل روی this اعمال میشود 
وقتی در یک کلاس بیش از یک متد synchronized داشته باشیم و توسط تردی یکی از آنها در حال استفاده باشد دیگر متد های synchronized توسط ترد های دیگر قابل استفاده نخواهند بود و باید صبر کنند تا قفل آزاد شود 

هر شی ای در جاوا میتواند به عنوان Lock استفاده شود 

synchronized block : در جاوا میتوان توسط synchronized block قفل را روی هر ابجکتی ایجاد کرد و فقط محدود به this نیست 
List<String> names;
synchronized (names){
   names.add( "sara" );
}

ّبلاک بالا به این معنی است که وقتی تردی وارد synchronized block شد ترد دیگری نمیتواند ابجکت names را در اختیار داشته باشد 
synchronized void m1(){
    run();
}
void m2(){
synchronized (this) {
run();
}
}


دو متد بالا کاملا یکسان هستند و وقتی از عبارت synchronized روی متد استفاده مکنیم مانند این است که داخل متد از synchronized block روی ابجکت this استفاده کرده باشیم 

ما میتوانیم متد های static را هم synchronized کنیم و وقتی تردی وارد یک متد synchronized شود قفل کل کلاس (و نه instance )را در اختیار میگیرد و شرایط سختگیرانه تر است

تعامل بین چند ترد :
گاهی لازم است دو ترد باهم تعامل داشته باشند مثلا یک ترد در میانه اجرا باید صبر کند تا ترد دیگری به آن خبر بدهد که میتواند ادامه کار را انجام دهد . متد های notify و wait برای تعامل بین ترد ها استفاده میشود این متد ها در کلاس Object هستند و بصورت final و native هستند 
وقتی یک ترد متد wait را روی یک ابجکت فراخوانی میکند اجرای ان ترد متوقف میشود و این توقف تا زمانی که ترد دیگر متد notify آن ابجکت را فراخوانی کند طول میکشد 
متد wait و notify تنها در صورتی قابل استفاده هستند که آن ابجکت در داخل synchronized block قرار داشته باشد 
پس یک ترد برای فراخوانی wait  و notify روی یک شی باید قفل آن شی را در اختیار داشته باشد وگرنه خطای IllegalMonitorStateException پرتاب میشود البته با فراخوانی wait روی ابجکت بلافاصله قفل آزاد میشود تا ترد های دیگر بتوانند وارد synchronized block شوند و notify را صدا بزنند تا از حالت waiting خارج شود متد wait کمی خاص تر است 

public class Name {
sycnchronized void m1(){
    wait(); }
}

synchronized (name){
   name.notify(); }

ما روی هر ابجکت تعدادی ترد میتوانیم داشته باشیم که wait کرده باشند ، هر ابجکتی فهرستی از ترد های منتظر دارد و با هر فراخوانی notify روی ابجکت یکی از آن ترد ها از حالت wait خارج میشود و اجرایشان را ادامه میدهند 
بجای فراخوانی notify میتوانیم notifyAll را هم میتوانیم فراخوانی کنیم و همه ترد ها را از حالت wait خارج کنیم 
متد wait میتواند برای حالت انتظارش زمان تعیین بکند و بعد از اتمام زمان اتوماتیک از حالت انتظار خارج میشود 

متد interrupt : 
گاهی ممکن است اجرای یک ترد به خاطر یکی از حالت های wait sleep join به حالت انتظار رفته باشد اگر در این حالت متد interrupt را فراخوانی کنیم ترد از حالت انتظار خارج میشود و احتمالا یک خطای InterruptException رخ خواهد داد 


Running State در ترد : به زمانی که ترد حالت کاری دارد و میتواند کد را اجرا کند Running State میگویند
Alive State : از زمان بوجود امدن یک ابجکت Thread تا لحظه اتمام فرایند کاری و قبل از مرگ آن ترد Alive State میگویند
با متد getState میتواند State ترد را دریافت کرد







نظرات  (۰)

هیچ نظری هنوز ثبت نشده است

ارسال نظر

ارسال نظر آزاد است، اما اگر قبلا در بیان ثبت نام کرده اید می توانید ابتدا وارد شوید.
شما میتوانید از این تگهای html استفاده کنید:
<b> یا <strong>، <em> یا <i>، <u>، <strike> یا <s>، <sup>، <sub>، <blockquote>، <code>، <pre>، <hr>، <br>، <p>، <a href="" title="">، <span style="">، <div align="">
تجدید کد امنیتی