ورود

View Full Version : سوال: سوال در مورد مدیریت ارتباط بین Thread ها



Sina.iRoid
چهارشنبه 26 آذر 1393, 17:33 عصر
سلام دوستان. یه سوالی داشتم، لطف می کنید اگر راهنماییم کنید.

اگه به کد ها دقت کنید، این برنامه یه تولید کننده داره و یه مصرف کننده. باید به ازای اجرای هربار تولید کننده، مصرف کننده هم اجرا بشه.

کد کلاس Q


package ir.blog.javairoid.main;


public class Q {

int n;
boolean valueSet = false;

synchronized int get(){
if (!valueSet) {
try {
wait();
} catch (InterruptedException e) {
System.out.println("Interrupted.");
}
}
System.out.println("Get: " + n);
valueSet = false;
notify();
return n;
}
synchronized void put(int n){
if (valueSet) {
try {
wait();
} catch (InterruptedException e) {
System.out.println("Interrupted.");
}
}

this.n = n;
valueSet = true;
System.out.println("Put: " + n);
notify();
}
}


کد کلاس Producer


package ir.blog.javairoid.main;


public class Producer implements Runnable {

Q q;

// Constructor
public Producer(Q q) {
this.q = q;
new Thread(this, "Producer").start();
}

@Override
public void run() {
int i = 0;
while (true) {
q.put(i++);
}
}
}


کد کلاس Consumer


package ir.blog.javairoid.main;


public class Consumer implements Runnable {

Q q;

// Constructor
public Consumer(Q q) {
this.q = q;
new Thread(this, "Consumer").start();
}

@Override
public void run() {
while (true) {
q.get();
}
}
}


و این هم کد کلاس اصلی


package ir.blog.javairoid.main;


public class MainClass {


public static void main(String[] args) {

Q q = new Q();

new Producer(q);
new Consumer(q);
}
}


دوستان سوال من در مورد کلاس Q هست. اصلا متوجه کاربرد متد های wait و notify نمیشم. و اینکه دستور if دقیقا چیه!؟ یعنی مقدارش false(ه) یا true!؟
ممنون میشم اگر در این چند مورد راهنماییم کنید.

Sina.iRoid
جمعه 28 آذر 1393, 15:10 عصر
از دوستان گرامی، کسی نیست من و راهنمایی کنه!؟:عصبانی++:

ahmad.mo74
شنبه 29 آذر 1393, 11:43 صبح
سلام :لبخند:

متد ()wait یعنی صبر کن و متد ()notify یعنی اوکی حله به کارت ادامه بده :)

اما اینا یعنی چی؟

اینجا ما یه کلاس Producer داریم و یه کلاس Consumer.

سناریو اینه که producer یه مقداری رو فراهم میکنه و consumer میره اونو برمیداره، اگر مقدار فراهم نشده بود consumer منتظر میمونه تا producer مقدار رو ست کنه و بعدش consumer رو notify کنه. یا اینکه producer مقدار رو ست میکنه و منتظر میمونه تا consumer بیاد اونو برداره بعدش producer رو notify کنه تا دوباره بره ست کنه! (ساده تر از این نمیشد توضیح داد)

درباره synchronized هم فکر کنم دیگه نیازی به توضیح نباشه.

پ.ن :

چنتا نکته درباره wait و notify :

اول اینکه از یک ترد نمیتونیم هم wait کنیم هم notify، یعنی فقط یک ترد میتونه wait رو صدا کنه (باعث میشه تا اون تردی wait رو کال کرده متوقف بشه) و ترد دیگه notify رو صدا کنه تا تردی که متوقف شده بود به کارش ادامه بده.
معمولا هم برای اینکار یک آبجکت به اسم lock (معمولا) میسازن (از هر کلاسی فرق نمیکنه ولی بیشتر از خود Object استفاده میکنن) و برای wait و notify کردن ترد اونو واسطه قرار میدن. اما اینجا مستقما از خود Q استفاده کرده.
من خودم بیشتر اینطوری ترجیح میدم بنویسم :

Queue :


package test;


/**
* @author avb
*/
public class Queue {


private final Object lock = new Object();
private boolean ready;
private Object value;


public Object get() {
synchronized (lock) {
if (!ready) {
try {
lock.wait();
} catch (InterruptedException ignored) {
}
}
ready = false;
lock.notify();
return value;
}
}


public void put(Object value) {
synchronized (lock) {
if (ready) {
try {
lock.wait();
} catch (InterruptedException ignored) {
}
}
this.value = value;
ready = true;
lock.notify();
}
}


}


Producer :


package test;


/**
* @author avb
*/
public class Producer implements Runnable {


private final Queue queue;


public Producer(Queue queue) {
this.queue = queue;
}


@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
queue.put(System.currentTimeMillis());
}
}


}


Consumer :


package test;


/**
* @author avb
*/
public class Consumer implements Runnable {


private final Queue queue;


public Consumer(Queue queue) {
this.queue = queue;
}


@Override
public void run() {
while (true) {
System.out.println(queue.get());
}
}


}


Main :


package test;


/**
* @author avb
*/
public class Main {


public static void main(String[] args) {
final Queue queue = new Queue();
new Thread(new Producer(queue)).start();
new Thread(new Consumer(queue)).start();
}


}