0

I cannot figure out how to stop a Thread in Java.

I have a function that creates the Thread and starts it. Now when I start the program, I want it to start the Thread. After that if the button is pressed then I want the Thread to stop and when the button is pressed again, I want the Thread to start over, or resume (it does not matter).

My function that creates the Thread:

private void startRecordingUserInput() {
    AudioDispatcher dispatcher =
            AudioDispatcherFactory.fromDefaultMicrophone(44100, 2048, 0);


    PitchDetectionHandler pdh = new PitchDetectionHandler() {
        @Override
        public void handlePitch(PitchDetectionResult res, AudioEvent e) {
            final float pitchInHz = res.getPitch();
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    pitchText.setText("" + pitchInHz);
                    gameView.setSingerArrowPitch(pitchInHz);
                    gameView.setCurrentTime(mid);
                    gameView.invalidate();
                }
            });
        }
    };
    AudioProcessor pitchProcessor = new PitchProcessor(PitchProcessor.PitchEstimationAlgorithm.FFT_YIN, 44100, 2048, pdh);
    dispatcher.addAudioProcessor(pitchProcessor);

    Thread audioThread = new Thread(dispatcher, "Audio Thread");
    audioThread.start();
} 

And the part where I start it and want to start/stop the Thread.

    //Start the Thread
    startRecordingUserInput();

    playRecordButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if(!isPlaying){

                //Start the Thread again if it is not running or 
                //make a new one

                isPlaying = true;

            } else if(isPlaying){

                //Stop the Thread

                isPlaying = false;

            }
        }
    });
Richard
  • 1,087
  • 18
  • 52
  • What is your question? – Turing85 Jun 11 '18 at 19:05
  • @Turing85 My question is, how can I Start and Stop the Thread when it is needed – Richard Jun 11 '18 at 19:07
  • 1
    I would basically follow this example (ignore the German in it): http://javawiki.sowas.com/doku.php?id=java:thread-pausieren . One basically extends a Thread and adds a flag, that one could set from outside the thread - e.g. in your listener in the GUI-thread. If the flag has been changed, the next time the if-statement is synchronously checked **inside** the run()-method, it will put any further processing on hold. There are also Thread-runners (such as `SwingWorker`, `Runnable` or the likes), that might ease your burden. – Igor Jun 11 '18 at 19:13
  • You have mutlipe layers of wrapping. You define your runnable, but this seems to do some GUI-related stuff, no actual processing. The `AudioDispatcher` seems to be the part doing all the work. All methods in `Thread` that could be used to implement what you want are marked deprecated. If you were to use e.g. `suspend()` and `resume()`, you would have to rely on `AudioDispatcher` to have those methods properly implemented. – Turing85 Jun 11 '18 at 19:29

3 Answers3

0

a thread runs until its run method completed, so if you want to keep on running it then add an infinite loop in the run method then inside run method add a condition for "isPlaying==false" then break the loop. again when you want to start the thread on button click then make "isPlaying=true" and call thread.start() method.

public void run() {
   while(true) {
      if(!isPlaying) {
         break;
      }
      // Do other stuff here.
   }
}
Kröw
  • 504
  • 2
  • 13
  • 31
MohdTausif
  • 498
  • 4
  • 13
  • Correct. Stop method in java has been deprecated for a long time now. Thus I'm afraid the only conclusive way of stopping a thread is to let it finish. However, if your thread is expected to enter in sleep or wait you can call Thread.interrupt() which will throw an exception and when properly handled, it'll be able to pull you out. – skY Jun 11 '18 at 19:21
  • yes instead of using an extra flag "isPlaying" you can use the method "isInterrupted()" in run method and if it is true then break the loop.basically when we call thread.interrupt() it just makes a flag true for the interruption and same flag is returned by isInterrupted() method. – MohdTausif Jun 11 '18 at 19:25
0

You can do it in many ways

You can get all running threads with

Thread.getAllStackTraces()

You can "un-safely" stop a thread by doing

Thread t;
t.stop(); 
//or
t.destroy();
//or 
t.suspend();
//Or to resume
t.resume();

Or, you can go the safe route, and learn synchronization, and use

Thread t;
t.wait();
t.notify();

Also, this to will not always work, but you can do

 boolean pause() { isPaused = !isPaused; }

 @Override
 public void run() {
      while (running) { if (!isPaused) doThread(); }
 }
Joe
  • 1,316
  • 9
  • 17
  • 1
    As much as I have read then using `destroy` and `stop` should be bad practice. – Richard Jun 11 '18 at 19:17
  • I would surround the check on pause with `synchronized(this) {...}` in order to not have the value changed while it's still being evaluated, hence creating a lock while performing the check. – Igor Jun 11 '18 at 19:18
  • I denoted the bad practiced methods as: "You can "un-safely" stop a thread by doing" – Joe Jun 11 '18 at 19:28
0

For anyone who might use TarsosDSP in the future and faces the same problem then the easiest way is to make a global dispatcher

dispatcher = AudioDispatcherFactory.fromDefaultMicrophone(22050,1024,0);

And simply stop the Thread with this:

dispatcher.stop();
Richard
  • 1,087
  • 18
  • 52