I’m guessing the 50% thing is because it’s a dual-core processor. Because your program isn’t multi-threaded, it’ll just shunt all instructions to 1 core of the processor.
Anyway, regarding wait/notify/backing-off:
Backing-Off/Polling:
By no means the most efficient way of checking if the buffer has space to add more data to it, but the easiest to understand. This is effectively a polling mechanism that checks if there’s space in the buffer to add more data. If there isn’t any space, it goes to sleep for a while, before checking again.
// Method to add more data to the buffer
public void addData() {
while (thereIsMoreToDecode) {
if (buffer.isFull()) {
Thread.sleep(500); // Sleep for 500ms
}
else {
// Add more data to the buffer
}
}
}
public static void main(String[] args) {
// Start a new add-data-to-buffer thread
new Thread(new Runnable() {
public void run() {
addData();
}
}).start();
// Do other stuff, like reading from the buffer
}
Thread wait/notify:
This is a tougher concept to understand: synchronization, locks, etc… but just as easy to implement. If you don’t already know about them (which I’ll assume) I’d probably recommend a primer in Java threads before trying this out.
In this case, the method that puts data on to the buffer is going to wait until there is more room before adding more data. What wait() means, is that the method goes to sleep until another thread tells it to wake-up (which happens when the notify() method is called) on the event that there is more room.
private int bufferSize = 2;
private int bufferUsed = 0;
// Putting data onto the buffer method
public synchronized void addData() {
while (thereIsMoreToDecode) {
// Decode OGG data ...
// Then put it onto the buffer if there's room
if (bufferUsed < bufferSize) {
// Queue the new data onto the buffer
bufferUsed++;
notify();
}
// Otherwise wait until there's room
else {
wait();
}
}
}
// Taking data off the buffer method
public synchronized void takeData() {
while (thereIsMoreToRead) {
// Only read if there is data in the buffer
if (bufferUsed > 0) {
// Read the data from the buffer
bufferUsed--;
notify();
}
// Otherwise, sleep until there is more
else {
wait();'
}
}
}
// Method to start the decoding and reading threads
public static void main(String[] args) {
// Create and start a new add-data-to-buffer thread
new Thread(new Runnable() {
public void run() {
addData();
}
}).start();
// Create and start a take-data-from-buffer thread
new Thread(new Runnable() {
public void run() {
takeData();
}
}).start();
}
This is all just examples and pseudo-code, but if you can wrap your head around what the wait() and nofity() methods do, as well as fill-in the gaps for actually putting data onto the buffers where I’ve just left comments, then you should be fine. The example that I’ve written above for wait/notify is similar to the one given to this chapter on multi-threading in Java (w/ a producers-consumers example) here:
http://java.sun.com/docs/books/tutorial/essential/threads/multithreaded.html