我创建了一个扩展Java的ThreadPoolExecutor的类,它使用它的线程来播放声音。此执行程序接收我创建的Sound类的对象,以允许一些基本操作(循环,暂停,恢复)。乍一看似乎完美无缺,除了一件事:如果我在Sound类的代码中删除了System.out.println调用(如下所示),我的声音可以暂停,但是他们拒绝恢复。如果我让println进入,恢复工作将完美无缺。
SoundController类
public class SoundController extends ThreadPoolExecutor
{
public SoundController()
{
super(2, Integer.MAX_VALUE, 60, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
setThreadFactory(new SoundThreadFactory());
prestartAllCoreThreads();
}
@Override
protected void beforeExecute(Thread thread, Runnable target)
{
super.beforeExecute(thread, target);
Sound sound = (Sound) target;
SoundThread soundthread = (SoundThread) thread;
sound.setLine(soundthread.getLine());
soundthread.setPriority(sound.getPriority());
}
protected static class SoundThreadFactory implements ThreadFactory
{
@Override
public SoundThread newThread(Runnable target)
{
return new SoundThread(target);
}
}
// When a new thread is created, create a new sound line for it to use.
private static class SoundThread extends Thread
{
private SourceDataLine line;
public SoundThread(Runnable target)
{
super(target);
setDaemon(true);
AudioFormat format = Core.loader().getSoundFormat();
int buffersize = Core.loader().getSoundBufferSize();
try
{
line = AudioSystem.getSourceDataLine(format);
line.open(format, buffersize);
line.start();
}
catch (LineUnavailableException e)
{
Core.loader().logException(e);
}
}
public SourceDataLine getLine()
{
return line;
}
}
}
声音等级
public class Sound implements Runnable
{
private enum SoundState
{
IDLE,
FINISHED,
PAUSED,
PLAYING,
}
private String url;
private int loopcount, priority;
private SourceDataLine line;
private SoundState state;
/**
* Creates a new Sound.
* @param url the sound's url
* @param loopcount the sound's loop count
* @param priority the sound's priority
*/
public Sound(String url, int loopcount, int priority)
{
this.url = url;
this.loopcount = loopcount;
this.priority = priority;
state = SoundState.IDLE;
}
/**
* Returns the priority of the sound.
* @return returns the sound's priority
*/
public int getPriority()
{
return priority;
}
/**
* Checks whether the sound has been paused.
* @return returns true if the sound is paused
*/
public boolean isPaused()
{
return state == SoundState.PAUSED;
}
/**
* Changes the data line to play the sound on.
* @param line a new source data line
*/
public void setLine(SourceDataLine line)
{
this.line = line;
}
/**
* Pauses the sound.
*/
public void pause()
{
state = SoundState.PAUSED;
}
/**
* Unpauses the sound.
*/
public void unpause()
{
state = SoundState.PLAYING;
}
/**
* Starts the sound.
*/
public void start()
{
// Equal to soundcontroller.execute(this)
Core.fireEvent(new Engine.AddSoundEvent(this));
}
/**
* Stops the sound.
*/
public void stop()
{
state = SoundState.FINISHED;
}
@Override
public void run()
{
AudioFormat format = Core.loader().getSoundFormat();
int buffersize = Core.loader().getSoundBufferSize();
byte[] buffer = new byte[buffersize];
state = SoundState.PLAYING;
int loop = loopcount;
while(state != SoundState.FINISHED)
{
try(AudioInputStream filestream = AudioSystem.getAudioInputStream(new File(url)))
{
try(AudioInputStream stream = AudioSystem.getAudioInputStream(format, filestream))
{
int bytecount = 0;
while(bytecount != -1)
{
// REMOVING THIS CALL RESULTS IN THE SOUND FAILING TO RESUME!
System.out.println(state);
if(state == SoundState.PLAYING)
{
bytecount = stream.read(buffer, 0, buffer.length);
if(bytecount != -1)
{
line.write(buffer, 0, bytecount);
}
}
}
}
}
catch(Exception e)
{
Core.loader().logException(e);
}
if(loop != -1)
{
loop--;
if(loop == 0)
{
state = SoundState.FINISHED;
}
}
}
}
}