我目前正在阅读一本书中关于Java Consumer-Producer解决方案的实现。
public class Producer extends Thread {
private IntBuffer buffer;
public Producer( IntBuffer buffer ){
this.buffer = buffer;
}
public void run(){
Random r = new Random();
while( true ){
int num = r.nextInt();
buffer.add( num );
System.out.println( “Produced “ + num );
}
}
}
public class Consumer extends Thread {
private IntBuffer buffer;
public Consumer( IntBuffer buffer ){
this.buffer = buffer;
}
public void run(){
while( true ){
int num = buffer.remove();
System.out.println( “Consumed “ + num );
}
}
}
public class IntBuffer {
private int index;
private int[] buffer = new int[8];
public void add( int num ){
while( true ){
if( index < buffer.length ){
buffer[index++] = num;
return;
}
}
}
public int remove(){
while( true ){
if( index > 0 ){
return buffer[--index];
}
}
}
}
IntBuffer b = new IntBuffer();
Producer p = new Producer( b );
Consumer c = new Consumer( b );
p.start();
c.start();
以下是我的几个问题:
根据这本书,这种方法使用繁忙的等待。这发生在哪里?根据我的理解,当一个线程正在等待另一个线程完成其执行而它可以恢复自己的执行之前,就会发生忙等待。通过使用wait()方法,线程在技术上是否仍然等待进行notify()调用?
为什么同步的添加/删除方法无法解决访问控制问题?我认为术语同步阻止了多个线程访问相同的代码段。
为什么在添加/删除方法中都有一个while(true)循环?
答案 0 :(得分:1)
它通过不断检查索引值的更改来实现此目的。例如,在add()方法中,只要index不小于buffer.length,该方法就永远不会返回。相反,它将继续检查,直到索引IS小于buffer.length,只有在调用remove()时才会发生。
然后,这是一个忙碌的等待。意思是,您实际上并没有使用停放线程的等待和通知机制,而是使用轮询线程。你会注意到这里没有提到wait()和notify()方法 - 它只是通过使用while(true)来阻塞线程。它与轮询端口和打开套接字以及异步从服务器接收更新之间的区别不同。
因为这些线程是故意相互阻塞的,所以你无法真正放弃同步add()和remove()方法 - 它只会导致死锁。