I beleive you can “stream” data in chunks, and then check how much is processed. So like you have a game loop for graphics you can have a loop for audio too and you can check how many chunks have been processed and appropriately top it up when when required by decoding more data.
Here some code form a very log time ago that shows how you could check things in the audio loop. It checks how much data has been processed and replaces it with new data if there is any.
// remove any buffers already played
int currentBuffersProcessed = sound.alGetSourcei(soundStream.getSoundId(), sound.AL_BUFFERS_PROCESSED);
System.out.println("Current Buffers Processed [" + currentBuffersProcessed + "]");
for (int i = 0; i < currentBuffersProcessed; i++)
int buffer = sound.alSourceUnqueueBuffers(soundStream.getSoundId());
buffer = sound.alGenBuffers();
System.out.println("Sound Stream Has More");
ByteBuffer sample = soundStream.readNextSample();
sound.alBufferData(buffer, (soundStream.getNumberChannels() > 1 ? sound.AL_FORMAT_STEREO16 : sound.AL_FORMAT_MONO16), sample, soundStream.getSampleRate());