• Post Reply Bookmark Topic Watch Topic
  • New Topic

TimerTasks now Dying When Executor Runs  RSS feed

 
Alvin Parker
Ranch Hand
Posts: 39
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am on a project that has had many developers before I came to it. When it was put together, everything was made static so I can not extend anything.

The program takes commands from a front end (different language) via a Socket and then does things and / or sends back messages.

Since I could not extend the existing system, I made a new project and created an interface between the old and the new packages. One of the things the new software does is listen to MIDI messages over a cable. In order to keep the native cable from failing with a single long running Thread, I configured the Threading as so :



Once this code runs, all other Threads seem to be blocked. In the pre-existing packages, there are a series of TimerTasks that run to do things like play a WAV sound for counting off song starts (e.g. "1" tick tick "2" tick tick "Set" tick tick "Go" tick tick and then the player I built starts playing and the listener I built start processing MIDI messages and sending them back to the front end. Now the TimerTasks never run.

Again, the TimerTask (and other Threads) are in the pre-existing packages. The new listener and player (and a few other things) are in the new packages. I know that my listeners are ready and working because I can press keys on my instrument and hear the notes play through my computer speakers (and output log messages from within the Thread). I also know that all the other Threads are blocked and not dead because if they were dead, my listener / player would be gone and I'd have ServerSocket error logs as well as other sorts of errors. I get no errors. The other Threads just seem to suspend.

I suspect that what is happening is that my run() method has become a long-running method that the main is waiting to complete and then blocking everything else while it's not complete. But, I'd love to know if I'm right on that or not. To fix this, do I have to make a Singleton and submit all my Runnables to it and have it add them to the Executor framework? I would rather not get into refactoring all that static code if I can avoid it. Is there some easy solution to this?

[EDITED: Typos]
 
Ulf Dittmer
Rancher
Posts: 42970
73
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
For starters, you should put logging code in the catch statement so you'll if something is going wrong. Basically, the code implements busy waiting - running an endless loop, permanently trying to create and start new MidiProcessorRunnables (assuming that midiIn != null). Is that what it should be doing? It doesn't feel right.
 
Alvin Parker
Ranch Hand
Posts: 39
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I do have loggers. I just cut them out of this snippet. None of my messages ever indicate any failure.

While playing a song, I have to watch what notes you're hitting. While not playing a song, I still output the sounds to your speakers in case you were wanting to play without being scored or just to diddle around. The MIDI in is a native (C++) package which I instantiate via JNI. Once it's there, the only way I can get messages out of it is to check it constantly.

I found that if I have one Thread running and you press a note, you'll hear it output many times until things start to right themselves. By putting in the Executor and making new Runnables every time, my notes are right on time. As an example, I can only process one note at a time but if you play a chord, the log files indicate that each note of the chord was processed 1 MS apart - this is important because humans can hear latency starting as low as 20 MS. But, as you said, I appear to have created a "busy waiting" scenario for the rest of the code. How do I both process notes immediately (when I don't get indication a note is there and have to check) while also not blocking everyone else?
 
Ulf Dittmer
Rancher
Posts: 42970
73
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You could put in a call to Thread.yield() and see whether that makes a difference.
 
Jaikiran Pai
Sheriff
Posts: 10447
227
IntelliJ IDE Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Have you tried taking a thread dump to see what activities the threads are up to? You might have to take a few thread dumps with a few seconds of gap between them.
 
Alvin Parker
Ranch Hand
Posts: 39
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No I have not. But I will. However, I have continued to test and what I find is.

I found that the ServerSocket is also still live but stops doing any work when this block runs too. It is not dead or the client would give me an output stream error on messages it is sending once everything except my listener halts.

I removed the code and the socket keeps handling messages and the TimerTasks complete. I think I should probably get into the C++ side and create an Observer instead.

[Edit]
I had tried Thread.yeild() when I wrote that. That made no difference. I even tried Thread.sleep(2000). That had the very interesting result of playing notes in queue two seconds apart until all the notes in queue were exhausted (which was fun). But it made no difference to the responsiveness of the rest of the system.
 
Jim Venolia
Ranch Hand
Posts: 248
2
Chrome Linux VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
1) Do you work for Rocksmith?

2) I don't know squat about sync'ing threads in Java. But I'm pretty good at it under various *nix's and embedded system OS's.

3) I'm a Java beginner, take the intent of the following code, not the actual code provided.

That said...

Were does midiIn come from? Did you open a socket or create a select() call to read it? From what I see you check it in a while(true) loop, but never set it.

Have you stepped through the code in a debugger? If the problem only occurs under load try this trick.

Provide some means of printing out traceArray and traceIndex. Under *nix I make a signal handler, then use the kill command to send the signal to my code. No clue how to do this in Java.

 
Alvin Parker
Ranch Hand
Posts: 39
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Great suggestions. I'm happy to report I got it working and I learned a few things from your posts as well.

I don't work for Rocksmith, but have a You Rock MIDI guitar. If you want to learn how to play guitar (in beta) or piano (or drums) and you have a MIDI cable and a MIDI instrument, I can help you out.

I solved this by using an Observer. Thee's a little more latency (notes were at 1 MS before and now are up to 5 MS apart). But now everyone is playing nice.

Thanks so much!
 
Consider Paul's rocket mass heater.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!