假设我有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;
}
}
答案 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
想要获取新值,则会在队列中出现新元素时等待。