how deal with time spent per thread?

I have a GUI and a loosely coupled object running on separate threads.

The JSlider on the GUI uses a ChangeListener to update a volatile variable on the object. The object consults this variable on a very frequent basis in a while loop (44100 times per second on average, as it is in the core of a sound playback routine, and consults once per frame).

Now, if the JVM doesn’t switch back and forth very often (I have an old Windows XP, Pentium 4, 3.2 GHz, 3GB RAM, so it it’s a simulated rather than a true multicore processing situation) then we have this happening: the volatile variable is updated as many as 10 times perhaps before the other thread is allowed to do anything, and thus the other thread sees a rather large jump because it only gets the last update.

Is there a way to alter the JVM to make it switch threads more often? Or is that a place one should not go? (Is it similar to the way one can tweak Garbage Collection frequency, perhaps?)

I suppose I could try to think in terms of putting the updates in a queue for consumption (so none are skipped). But I’ll also have to figure out how to spread them out. Dang. Is this what is normally done in such a situation? I can put more smoothing in the response to the slider, but that makes it rather laggy.

Sounds like you’ve got the wrong solution. What exactly is this variable controlling?

If it’s just the visual jump you don’t like then interpolate between your old and new values. If you actually need to handle all the values it can take then put each variable change event into a list and process that from the other thread.

Alternatively you can tinker with the thread priorities but that’s liable to be tricky and only fix the problem on your machine.

The interval at which threads are switched is determined with the OS.

If you want higher granularity, you need to enqueue lots of tiny (!) tasks on the EDT so you can stay on the same thread most of the time. Even then your thread will be swiched every now and then…

You’re not on a realtime OS, so you shouldn’t make any assumptions on how long the delays are between thread executions.

So you’re polling? Polling = bad. So you have a single producer/single consumer model?

You can stick a Thread.yield() in your ChangeListener. But I concur with everyone else who’s posted that you’re Doing It Wrong™

Thanks for the replies! It is very heartening to see this willingness to help out.

[quote]Sounds like you’ve got the wrong solution. What exactly is this variable controlling?
[/quote]
The goal is to have a “real-time” gui control of the volume of an ongoing sound being played via a SourceDataLine. My AudioSystem does not expose a MASTER_VOLUME or any other controls for SourceDataLines, though it does so for Clips. From what I am reading, this is probably a good thing. The proliferation of controls slows down the processing of SourceDataLines and according to “Killer Game Programming in Java” most were removed in 1.5.

So, I have a “SoundCue” object which exposes a volatile “desiredVolume” instance variable, and has an internal “currentVolume” variable. Both are floats. At the point where we get a buffer of byte data from the AudioInputStream, I iterate through that buffer and multiply the “currentVolume” float (between 0 and 1) to the audio value. Before doing so, I consult the “desiredVolume” and increment the “currentVolume” towards it. I increment once per “frame”. This might seem extravagant in an inner loop at a crucial point, but I think operations like filtering are commonly done at this stage and are considerably more involved.

if (currentVolume < desiredVolume)
{
    currentVolume += 0.0001;
} else {
    currentVolume -= 0.0001;
}

If the increment value is large (while remaining small enough so as to not cause clicks), and the updates from the JSlider stream are in effect “collapsed”, then there will a staircase effect to the volume changes as the currentVolume races up to meet the desiredVolume. If the increment is small, the changes are smoother but are rather laggy. I am annoyed at the degree of lag I’m getting now and was hoping for a bit more responsiveness.

Okay this window is starting to jump around and there are more helpful suggestions to answer, so I will reply in multiple posts.

[quote]You’re not on a realtime OS, so you shouldn’t make any assumptions on how long the delays are between thread executions.
[/quote]
Has anyone investigated various OS implementations and timed them? I know in “Killer Game Programming in Java” the author lists some common timings for different OS, for example, my Windows XP supposedly has OS updates at around 15msec.

But the “collapsing” of the JSlider data, I guess I was assuming the rate of JVM thread switching would more closely match the rate at which the ChangeListener events are read. If the JVM chooses to give the ChangeListener, say, enough processing time to read 10 events, then I’ve made 10 updates to the same variable without any other thread getting the opportunity to read the intermediate values.

I was estimating 10 events because that is how many changes are sometimes listed in a row via printlns in the ChangeListener routine and the sound-processing routine in the other thread. I get what seemed like big chunks from each routine, in turn, via these printlns.

[quote]So you’re polling? Polling = bad. So you have a single producer/single consumer model?
[/quote]
I’m not sure technically if what I’m doing is “polling”. Yes, there is a single producer and a single consumer. I think what I’m doing is called “loose coupling”. The AudioCue Object which receives the values from the JSlider does so via a volatile instance variable called “desiredVolume”. I originally learned to refer to this as a “push” rather than a “pull,” as it is the JSlider that initiates the update, placing the value in the AudioCue’s volatile “desiredVolume” variable. I’m guessing a “poll” is similar to a “pull”?

Both Riven and OrangyTang refer to the possibility of enqueuing the data from the JSlider. This might help. I’d have to manage the rate at which the values are consumed at the receiving end. Maybe I’ll do something like not update the “desiredVolume” with the queue value until the “currentVolume” has actually reached it. Any lagginess will then be mostly driven by the degree to which the JSlider has control of the JVMs attention, if that amount is greater than the time it takes to process the volume changes (which can be set to happen very quickly).

Last reply to the set of replies!

[quote]You can stick a Thread.yield() in your ChangeListener. But I concur with everyone else who’s posted that you’re Doing It Wrong™
[/quote]
This sounds really intriguing! Since it is the ChangeListener’s “hogging” of the JVM that I think is affecting the response, forcing it to relinquish makes good sense as a try. But it could have the side effect of causing a pileup on the EDT. I will try it out.

I’m also considering that maybe the degree of lagging, once I “tune” the receiving end’s change increment, is tolerable. I should compare it to the “real-time” responsiveness of my digital audio mixer volume controls. I don’t recall noticing a problem there, though.

EDIT: the slider on Sonar6 Homestudio in fact has a bit of a “zippering” artifact. So maybe I can consider that tolerable as I never noticed or cared about it before.

EDIT#2&3: the inclusion of Thread.yield() in the ChangeListener gives a marked improvement in performance! No signs yet of backup in the EDT. The printlns, though are still very bunched. So, I’m guessing my reliance on println as a way of gauging the JVM switching is probably misguided. Should maybe do something like write to a log instead. (no, I let my perceptions fool me, now it seems pretty similar with or without)

Thanks again to everyone who has pitched in!

I would consider using a Swing timer to send the audio data. That way you remove the cross-thread communication.

Thanks, again. Am currently just launching a generic Thread and it seems to be working fine. I think I’m good now. I’m not totally happy with the response but it seems acceptable for the purpose of the project I’m working on, where the focus is on presenting the sounds, not the gui.

I’m looking forward to showing off the results in the Showcase before too long, maybe by next week since 95% of Memorial Day weekend is booked. I’m all psyched and ready to program the rest of the night, but I have to be up for a 9-5 shift tomorrow morning! Dangity.