let's say i have 3 classes: 1. Storage which contains just one integer. 2. Counter which contains a thread inside who's responsible for counting (0,1,..,k) and stores each iteration of the loop index in Storage class. 3.Printer which contains a thread who's responsible for reading the value in class Storage and print it.
now i have to create a main class which creates these 3 objects runs the threads of Counter and Printer , and everynumber from(0,1,..,k) has to be printed just once and in the right order.
how do i synchronize the access to my Storage class so first i put a number inside Storage with Counter ,than print it with my Printer class ?
here's what i've wrote so far:
public class Storage {
private int num;
public Storage(){
}
public synchronized void setNum(int num){
this.num = num;
}
public synchronized int getNum(){
return num;
}
public class Counter implements Runnable {
Storage s;
public Counter(Storage t){
s = t;
}
@Override
public void run() {
int i = 0;
while(true){
s.setNum(i++);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class Printer implements Runnable {
Storage s;
public Printer(Storage s){
this.s= s;
}
@Override
public void run() {
while(true){
System.out.println(s.getNum());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class mainProg {
public static void main(String[] args){
Storage s = new Storage();
Counter c = new Counter(s);
Printer p = new Printer(s);
Thread c1 = new Thread(c);
Thread p2 = new Thread(p);
c1.start();
p2.start();
}
}
EDIT: i found out a solution, here it is:
public class Storage {
private int num;
private boolean available = false;
public Storage(){
}
public synchronized void setNum(int num){
while(available){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
available = true;
notifyAll();
this.num = num;
}
public synchronized int getNum(){
while(!available){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
available = false;
notifyAll();
return num;
}
}
This approach won't work, because it's not guaranteed that for every cycle of Counter
a cycle of Printer
will be executed in a parallel thread. You need to be able to store more than a one value in your Storage
. You can use BlockingQueue
here and rewrite your Storage
class like this:
public class Storage {
private BlockingQueue<Integer> numbers = new LinkedBlockingQueue<Integer>();
public void setNum(int num) {
try {
this.numbers.put(num);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
public int getNum() {
try {
return numbers.take();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
Note that if BlockingQueue
is empty and Printer
wants to get a new value, it will wait while a new element occurrs in the queue.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.