调用wait()会使我刚刚编写的变量为空

时间:2017-02-07 20:10:39

标签: java multithreading concurrency

我正在编写一个具有两个振荡器的合成器应用程序,每个振荡器都在自己的线程中运行。我想要做的是混合来自这两个振荡器的信号。当振荡器填充缓冲区时,它会通过调用其同步方法SynthMixer将其传递给sendBuffer()对象。

package mixer_test;

public class SynthMixer {

Synth synth;
double[] buffer1, buffer2;
boolean buffersProcessed;


public SynthMixer(Synth synth){

    buffer1 = null;
    buffer2 = null;
    this.synth = synth;
}

public synchronized void sendBuffer(double[] buffer) {

        if (buffer1 == null) {

            buffersProcessed = false;

            buffer1 = new double[Synth.bufferSize];

            for (int i = 0; i < Synth.bufferSize; i++) {
                buffer1[i] = buffer[i];
            }

            try {

                while(!buffersProcessed) {
                    wait();
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        } else {

            buffer2 = buffer;

            mixAndPass();

            buffer1 = null;
            buffer2 = null;

            buffersProcessed = true;
            notify();
        }
}

private void mixAndPass(){

    double[] outBuffer = new double[Synth.bufferSize];

    for(int i = 0; i < Synth.bufferSize; i++){

        outBuffer[i] = (buffer1[i] + buffer2[i])/2;
    }

    synth.passBuffer(outBuffer);
  }
}



package mixer_test;

public class Oscillator  {

WaveShape wave;
boolean hold;
SynthMixer mixer;

public Oscillator(WaveShape wave, SynthMixer mixer){

    this.wave = wave;
    this.mixer = mixer;
    hold = true;

}

public void start(int frequency){


    wave.setFrequency(frequency);

    Thread oscillatorLoop = new Thread(new Runnable(){

        public void run(){

            int sampleNo = 0;
            double[] buffer = new double[Synth.bufferSize];

            while(hold){

                for(int i = 0; i < Synth.bufferSize; i++){

                    buffer[i] = wave.getSample(sampleNo + i);
                }

                mixer.sendBuffer(buffer);
                sampleNo += Synth.bufferSize;
            }

        }
    });

    oscillatorLoop.start();
}

public void stop(){
    hold = false;
}

}


package mixer_test;

public class Synth {

public static final int sampleRate = 44100;
public static final int bitDepth = 16;
public static final int bufferSize = 512;


Oscillator osc1, osc2;
SynthMixer mixer;
Amp amp1; // converts double[] to byte[] and writes to SourceDataLine instance

public Synth(){

    mixer = new SynthMixer(this);
    osc1 = new Oscillator(WaveShape.SINE, mixer );
    osc2 = new Oscillator(WaveShape.SINE, mixer);
    amp1 = new Amp();
}

public void passBuffer (double[] buffer){

    amp1.sendBuffer(buffer);
}


public void play(){

    osc2.start(400);
    osc1.start(420);

}

public static void main (String[] args){

    Synth synth = new Synth();
    synth.play();

}
}

编写此代码时我的想法如下:

其中一个振荡器让我们说在线程A上运行的Osc A完成填充缓冲区并调用sendBuffer()。线程A保持SynthMixer对象锁定,因此即使线程B上的振荡器完成渲染缓冲区,它也会在调用sendBuffer()之前等待,直到锁被释放。因此,线程A调用sendBuffer(),buffer1字段为null,因此if语句执行将传递的缓冲区写入此字段。然后线程A等待释放锁,因此线程B可以调用该方法。现在buffer1不再为null,所以我们将振荡器B传递的缓冲区写入buffer2字段。 mixAndPass()接受两个缓冲区并将其混合。在此之后notify()唤醒线程A并且该进程重复下一个缓冲区。

但效果是只有通过的信号才是最后启动线程的振荡器的信号。在调试代码时,我可以看到,当调用wait()时,buffer1的值突然变为null。我无法理解为什么会这样,并且非常感谢有关如何使其正常工作的解释和建议。

0 个答案:

没有答案