Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
关于Java生产者消费者解决方案的问题_Java_Multithreading_Concurrency_Thread Safety - Fatal编程技术网

关于Java生产者消费者解决方案的问题

关于Java生产者消费者解决方案的问题,java,multithreading,concurrency,thread-safety,Java,Multithreading,Concurrency,Thread Safety,我目前正在阅读一本书中关于Java消费生产者解决方案的实现 public class Producer extends Thread { private IntBuffer buffer; public Producer( IntBuffer buffer ){ this.buffer = buffer; } public void run(){ Random r = new Random(); while( t

我目前正在阅读一本书中关于Java消费生产者解决方案的实现

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();
公共类生成器扩展线程{
私有IntBuffer;
公共生产者(IntBuffer){
this.buffer=缓冲区;
}
公开募捐{
随机r=新随机();
while(true){
int num=r.nextInt();
buffer.add(num);
系统输出打印项次(“生成”+num);
}
}
}
公共类使用者扩展线程{
私有IntBuffer;
公共消费者(IntBuffer){
this.buffer=缓冲区;
}
公开募捐{
while(true){
int num=buffer.remove();
系统输出打印项次(“已消耗”+num);
}
}
}
公共类IntBuffer{
私有整数索引;
私有int[]缓冲区=新int[8];
公共无效添加(int num){
while(true){
if(索引0){
返回缓冲区[--索引];
}
}
}
}
IntBuffer b=新的IntBuffer();
生产者p=新生产者(b);
消费者c=新消费者(b);
p、 start();
c、 start();
以下是我的几个问题:

  • 根据这本书,这种方法使用忙等待。这种情况发生在哪里?据我所知,当一个线程正在等待另一个线程完成其执行,然后才能恢复其自身的执行时,就会发生忙等待。通过使用wait()方法,线程在技术上不会一直等到notify()吗有人打电话吗

  • 为什么同步添加/删除方法不能解决访问控制问题?我认为术语同步阻止多个线程访问同一代码段

  • 为什么在add/remove方法中都有while(true)循环

  • 本质上,while(true)是为了确保,一旦缓冲区满了,每个方法都将阻塞,直到调用另一个方法。换句话说,生产者将无法生产另一个,直到消费者消费了一个
  • 它通过不断检查索引值的更改来实现这一点。例如,在add()方法中,只要索引不小于buffer.length,该方法就永远不会返回。相反,它将不断检查,直到索引小于buffer.length,这只会在调用remove()时发生

  • 因此,这是一个繁忙的等待。这意味着,实际上您并没有使用停止线程的等待和通知机制,而是使用轮询机制。您会注意到这里没有提到wait()和notify()方法-它只是使用while(true)来阻止线程。这与轮询端口和打开套接字以及从服务器异步接收更新之间的区别没有什么不同

  • 因为这些线程是故意相互阻塞的,所以同步add()和remove()方法是无法避免的——这只会导致死锁


  • 你的
    3
    回答了你的
    1
    @SotiriosDelimanolis-不是
    while(true)
    只是等待?。我的意思是他不是在等待任何条件实现。@TheLostMind
    中的
    if
    中的条件,而
    中的
    则在
    中。请注意每个
    返回
    。它只是等待,是的,但也阻止方法返回,直到if()中的条件出现为止语句变为true,此时then子句从while循环和方法中返回。@SotiriosDelimanolis-Ah。我没有正确地看到
    if
    条件。谢谢:)谢谢。现在我理解了代码的忙等待问题。但是,就同步添加和删除方法而言,是什么导致了死锁?即使使用while(true)循环,add方法的block on不是仍然允许remove方法修改bug吗?或者缓冲区数组本身被阻止访问add/remove方法在while(true)循环中吗?最后,我想wait()实际上会释放资源,而不是用while(true)持续占用它循环。如果同步add()和remove()方法,则它们用作锁的共享对象是“this”(IntBuffer的特定实例)。因此,同步可防止在任何线程仍在此类上执行任何同步方法时调用此实例中的任何方法。自调用add()以来阻塞,直到从另一个线程调用remove(),并且synchronized阻止另一个线程进入remove()方法,add()将永远阻塞。