线程同步问题

时间:2016-02-04 15:03:57

标签: java multithreading

假设我有3个班级: 1.仅包含一个整数的存储。 2.包含内部线程的计数器,负责计数(0,1,..,k)并将每个循环索引的迭代存储在Storage类中。 3.Printer包含一个负责读取类Storage中的值并打印它的线程。

现在我必须创建一个创建这3个对象的主类运行计数器和打印机的线程,并且(0,1,..,k)的每个数字必须只打印一次并且顺序正确。< / p>

如何同步对我的Storage类的访问,所以首先我在Storage with Counter中放一个数字,而不是用我的Printer类打印它?

这是我到目前为止所写的内容:

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();

}
}
编辑:我发现了一个解决方案,现在是:

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;
}
}

1 个答案:

答案 0 :(得分:1)

这种方法不起作用,因为不能保证Counter的每个循环都会在并行线程中执行Printer的循环。您需要在Storage中存储多个值。 您可以在此处使用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);
    }
}
}

请注意,如果BlockingQueue为空且Printer想要获取新值,则会在队列中出现新元素时等待。