while 循环的奇怪行为
Strange behavior from a while loop
所以我在写一个视频播放库,细节不重要。发生的事情是这段代码需要 运行 在解码器线程的 运行() 方法的末尾:
System.out.println("Video decoding complete");
int a = 0, b = 0;
do
{
a = pictures.getCount();
b = samples.getCount();
}while(a > 0 || b > 0);
Gdx.app.log("Status", videoPath + " completed playing successfully.");
videoComplete = true;
问题是,任何通过 do{}while 的东西都不会执行。这是奇怪的部分,这段代码在 while 循环中添加 System.out.println 时执行:
System.out.println("Video decoding complete");
int a = 0, b = 0;
do
{
System.out.println("Waiting for packets to drain.");
a = pictures.getCount();
b = samples.getCount();
}while(a > 0 || b > 0);
Gdx.app.log("Status", videoPath + " completed playing successfully.");
videoComplete = true;
我怀疑编译器知道我正试图将它变成 运行 一个什么都不做的循环,它只是剪掉代码或其他东西。但我真的不知道发生了什么。如果有人比我更了解,我希望有更好的解决方案。这么简单的事情我就挂在这里了!
我的猜测是 pictures.getCount() 和 samples.getCount() 读取非 volatile
字段。当您只读取一个非易失性字段时,出于性能原因,它可以被内联,但是如果您执行类似调用 synchronized
方法的操作(并且 System.out 是同步的),它不会以这种方式优化代码并且每次都必须执行查找。
我建议你尝试添加一个空的同步块,看看它是否仍然有效,即这样做而不是 println
synchronized(this) { }
我最终按照@slim 的建议这样做了:
System.out.println("Video decoding complete");
this.decoderComplete = true;
//wait until notified that packets are done draining
synchronized(this)
{
try {
this.wait();
} catch (InterruptedException e) {
videoComplete = true;
this.container.close();
e.printStackTrace();
}
}
Gdx.app.log("Status", videoPath + " completed playing successfully.");
videoComplete = true;
this.container.close();
在另一个线程中,一旦我们知道我们已经完成了所有数据包的读取:
if(this.packetHandlerRunnable.getNumAudioPackets() <= 0
&& this.packetHandlerRunnable.getNumVideoPackets() <= 0
&& this.packetHandlerRunnable.isDecoderComplete())
{
synchronized(packetHandlerRunnable)
{
this.packetHandlerRunnable.notify();
}
}
所以我在写一个视频播放库,细节不重要。发生的事情是这段代码需要 运行 在解码器线程的 运行() 方法的末尾:
System.out.println("Video decoding complete");
int a = 0, b = 0;
do
{
a = pictures.getCount();
b = samples.getCount();
}while(a > 0 || b > 0);
Gdx.app.log("Status", videoPath + " completed playing successfully.");
videoComplete = true;
问题是,任何通过 do{}while 的东西都不会执行。这是奇怪的部分,这段代码在 while 循环中添加 System.out.println 时执行:
System.out.println("Video decoding complete");
int a = 0, b = 0;
do
{
System.out.println("Waiting for packets to drain.");
a = pictures.getCount();
b = samples.getCount();
}while(a > 0 || b > 0);
Gdx.app.log("Status", videoPath + " completed playing successfully.");
videoComplete = true;
我怀疑编译器知道我正试图将它变成 运行 一个什么都不做的循环,它只是剪掉代码或其他东西。但我真的不知道发生了什么。如果有人比我更了解,我希望有更好的解决方案。这么简单的事情我就挂在这里了!
我的猜测是 pictures.getCount() 和 samples.getCount() 读取非 volatile
字段。当您只读取一个非易失性字段时,出于性能原因,它可以被内联,但是如果您执行类似调用 synchronized
方法的操作(并且 System.out 是同步的),它不会以这种方式优化代码并且每次都必须执行查找。
我建议你尝试添加一个空的同步块,看看它是否仍然有效,即这样做而不是 println
synchronized(this) { }
我最终按照@slim 的建议这样做了:
System.out.println("Video decoding complete");
this.decoderComplete = true;
//wait until notified that packets are done draining
synchronized(this)
{
try {
this.wait();
} catch (InterruptedException e) {
videoComplete = true;
this.container.close();
e.printStackTrace();
}
}
Gdx.app.log("Status", videoPath + " completed playing successfully.");
videoComplete = true;
this.container.close();
在另一个线程中,一旦我们知道我们已经完成了所有数据包的读取:
if(this.packetHandlerRunnable.getNumAudioPackets() <= 0
&& this.packetHandlerRunnable.getNumVideoPackets() <= 0
&& this.packetHandlerRunnable.isDecoderComplete())
{
synchronized(packetHandlerRunnable)
{
this.packetHandlerRunnable.notify();
}
}