در این مقاله، متد () water برای کنترل thread و متدهای notify() / notifyAll() را بررسی خواهیم کرد . این متدها در کلاس پایه java.lang.Object تعریف شدهاند و بر این اساس، مکانیسمهای ارثی که در جاوا هستند، این متدها را به طور مطلق برای همه کلاسها ارائه میکنند. یعنی وقتی کلاس خود و اشیای آن را ایجاد می کنید، همیشه می توانید این متدها را فراخوانی کنید.
روش های wait() و notify()/notifyAll() چگونه کار می کنند؟
- صبر کن() . به طور خلاصه، این روش مانیتور را آزاد می کند و رشته فراخوان را در حالت انتظار قرار می دهد تا زمانی که رشته دیگری متد notify() / notifyAll() را فراخوانی کند .
- اعلام کردن() . کار رشتهای را ادامه میدهد که متد wait() قبلاً فراخوانی شده بود.
- متد notifyAll() تمام رشتههایی را که قبلاً متد ()watch آنها فراخوانی شده بود، از سر میگیرد.
-
انتظار باطل نهایی بومی عمومی (تایم اوت طولانیMillis) InterruptedException را پرتاب می کند . باعث می شود تا رشته فعلی منتظر بماند تا بیدار شود. معمولاً با اطلاع یا قطع شدن، یا تا زمانی که مقدار مشخصی از زمان واقعی سپری شود، اتفاق می افتد.
-
عمومی void wait() InterruptedException را می اندازد . تصادفی نیست که روشی بدون پارامتر به عنوان روش دوم نوشتیم. در واقع، اگر به کد آن نگاه کنید، به اولین نوع روش اشاره دارد، فقط آرگومان 0L را دارد.
-
انتظار نهایی عمومی (تایم اوت طولانی، نانوهای داخلی) . باعث می شود تا رشته فعلی منتظر بماند تا بیدار شود، معمولاً با اطلاع رسانی یا قطع شدن، یا تا زمانی که مقدار مشخصی از زمان واقعی سپری شود.
مثال روش Wait()
در اینجا ما یکی از محبوب ترین مثال ها را داریم که نحوه کار این روش را نشان می دهد. فرض کنید ما یک فروشگاه، یک تولید کننده و یک مصرف کننده داریم. سازنده برخی از محصولات تولیدی را به فروشگاه منتقل می کند و پس از آن مصرف کننده می تواند آنها را تحویل بگیرد. اجازه دهید تولیدکننده به ترتیب 8 کالا تولید کند، مصرف کننده باید همه آنها را بخرد. اما در عین حال نمی توان بیش از 6 قلم کالا به طور همزمان در انبار باشد. برای حل این مشکل از متد ()water و notify() استفاده می کنیم . بیایید سه کلاس را تعریف کنیم: Market ، Manufacturer و Client . متد Manufacturer در run() 8 محصول را با استفاده از متد put() خود به شی Market اضافه می کند . کلاینت در متد run() در یک حلقه متد get شی Market را برای دریافت این محصولات فراخوانی می کند. متدهای put و get کلاس Market همگام هستند. برای پیگیری حضور کالاها در کلاس Market ، مقدار متغیر آیتم را بررسی می کنیم. متد get() برای بدست آوردن یک محصول فقط در صورتی باید فعال شود که حداقل یک محصول وجود داشته باشد. بنابراین در روش get بررسی می کنیم که آیا محصول موجود نیست. اگر آیتم در دسترس نباشد، متد wait() فراخوانی می شود. این متد مانیتور شی Market را آزاد می کند و متد get را مسدود می کند تا زمانی که متد notify() در همان مانیتور فراخوانی شود. هنگامی که یک آیتم در متد put() اضافه می شود و () notify فراخوانی می شود، متد get() مانیتور را دریافت می کند. پس از آن، مشتری ما یک مورد دریافت می کند. برای انجام این کار، یک پیام نمایش داده می شود و مقدار مورد کاهش می یابد. در نهایت، فراخوانی متد notify() به متد put() سیگنال می دهد تا ادامه یابد. در متد ()put ، منطق مشابه کار میکند، فقط حالا اگر بیش از 6 محصول در بازار وجود نداشته باشد، متد put() باید کار کند .class Market {
private int item = 0;
public synchronized void get() {
//here we use wait() method
while (item < 1) {
try {
wait();
}
catch (InterruptedException e) {
}
}
item--;
System.out.println("A client has bought 1 item...");
System.out.println("Items quantity in Market warehouse... " + item);
notify();
}
public synchronized void put() {
//here we use wait() method when the Warehouse is full
while (item >= 6) {
try {
wait();
}
catch (InterruptedException e) {
}
}
item ++;
System.out.println("Manufacturer has added 1 more item...");
System.out.println("Now there are " + item + " items in Warehouse" );
notify();
}
}
class Manufacturer implements Runnable {
Market market;
Manufacturer(Market market) {
this.market = market;
}
public void run() {
for (int i = 0; i < 8; i++) {
market.put();
}
}
}
class Client implements Runnable {
Market market;
Client(Market market) {
this.market = market;
}
public void run() {
for (int i = 0; i < 8; i++) {
market.get();
}
}
}
//wait() method test class
public class WaitTest {
public static void main(String[] args) {
Market market = new Market();
Manufacturer manufacturer = new Manufacturer(market);
Client client = new Client(market);
new Thread(manufacturer).start();
new Thread(client).start();
}
}
در اینجا با استفاده از wait() در متد get() منتظر هستیم تا Manufacturer آیتم جدیدی اضافه کند. و بعد از افزودن، notify() را فراخوانی می کنیم ، مثل اینکه می گوییم یک مکان در Warehouse رایگان شده است و می توانید تعداد بیشتری اضافه کنید. در متد put() با استفاده از wait() منتظر آزاد شدن فضا در Warehouse هستیم . پس از خالی شدن فضا، آیتم را اضافه می کنیم، notify() رشته را شروع می کند و Client می تواند آیتم را انتخاب کند. این هم خروجی برنامه ما:
سازنده 1 مورد دیگر اضافه کرده است ... اکنون 1 مورد در انبار وجود دارد سازنده 1 مورد دیگر اضافه کرده است ... اکنون 2 مورد در انبار وجود دارد سازنده 1 مورد دیگر اضافه کرده است ... اکنون 3 مورد در انبار وجود دارد. اضافه شد 1 مورد دیگر... اکنون 4 مورد در انبار وجود دارد. 1 عدد... تعداد اقلام در انبار مارکت... 5 مشتری 1 عدد خریده است... تعداد اقلام در انبار مارکت... 4 مشتری 1 عدد خریداری کرده است... تعداد اقلام در انبار مارکت... 3 یک مشتری 1 قلم خرید ... تعداد اقلام در انبار مارکت ... 2 مشتری 1 کالا خریده است ... تعداد اقلام در انبار مارکت ... 1 مشتری 1 قلم خرید ... تعداد اقلام در انبار مارکت ... 0 تولید کننده 1 مورد دیگر اضافه کرده است ... اکنون 1 مورد در انبار وجود دارد سازنده 1 مورد دیگر ... اکنون 2 کالا در انبار وجود دارد مشتری 1 مورد خریداری کرده است ... تعداد اقلام در انبار بازار ... 1 مشتری 1 کالا خریده است ... تعداد اقلام در انبار مارکت ... 0 فرآیند با کد خروجی تمام شد 0
GO TO FULL VERSION