简体   繁体   English

线程同步问题

[英]threads synchronization issue

let's say i have 3 classes: 1. Storage which contains just one integer. 假设我有3个类:1.仅包含一个整数的存储。 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. 2.计数器,其中包含一个线程,该线程负责计数(0,1,..,k),并将循环索引的每次迭代存储在Storage类中。 3.Printer which contains a thread who's responsible for reading the value in class Storage and print it. 3.Printer包含一个线程,该线程负责读取Storage类中的值并进行打印。

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. 现在我必须创建一个主类,该主类将创建运行Counter和Printer线程的这3个对象,并且from(0,1,..,k)中的每个数字都必须仅按正确的顺序打印一次。

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 ? 我该如何同步对Storage类的访问,因此首先我将一个数字放入带有Counter的Storage中,而不是使用Printer类进行打印?

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. 这种方法行不通,因为不能保证在Counter的每个周期中都会在并行线程中执行Printer的周期。 You need to be able to store more than a one value in your Storage . 您需要能够在Storage存储多个值。 You can use BlockingQueue here and rewrite your Storage class like this: 您可以在此处使用BlockingQueue ,然后像这样重写Storage类:

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. 请注意,如果BlockingQueue为空并且Printer要获取新值,则它将等待队列中出现新元素。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM