как вызвать один и тот же поток из другого прослушивателя действий

#java #multithreading #user-interface #actionlistener

#Ява #многопоточность #пользовательский интерфейс #список действий

Вопрос:

Я создаю графический интерфейс для музыкального плеера, у меня есть 2 кнопки, которые я хочу запустить в одном потоке, но на разных слушателях действий, одна из которых должна воспроизводить музыку, а другая-останавливать музыку. Вот мой код:

 ActionListener bl2 = new ActionListener() { // play button   @Override  public void actionPerformed(ActionEvent e) {  System.out.println("listener1"   Thread.currentThread().getName());  System.out.println("beep"); //created a new thread here so that my GUI won't freeze up  Runnable runnable = () -gt; {  cl.play();  };  Thread thread = new Thread(runnable);  thread.start();  }   };  ActionListener bl3 = new ActionListener() { //supposedly to stop the music which the other thread is running  @Override  public void actionPerformed(ActionEvent e) {  cl.stop();   }  };  

У меня также есть кнопка паузы, чтобы можно было приостановить музыку. Моя проблема в том, что я не знаю, как остановить мою музыку всякий раз, когда я нажимаю кнопку «Стоп» в своем графическом интерфейсе, она выполняется (у меня был метод, распечатываемый всякий раз, когда он вызывается), но не останавливает музыку, поэтому я думаю, что для остановки моей музыки мне нужно вызвать свой метод в том же потоке, в котором работает кнопка воспроизведения, это правильно? Как мне это сделать? Спасибо.

Ответ №1:

Вам не нужно вызывать тот же метод, что и в запущенном потоке, вы можете использовать общее логическое значение «volatile» в синхронизированном методе в потоке «control».

Давайте назовем это логическое значение «играющим»; Затем вы будете часто проверять значение этого логического значения в запущенном потоке. И в классах контроллеров вы могли бы затем изменить значение этого логического значения на false, если вы хотите, чтобы бегущий поток прекратил воспроизведение, а затем вы могли бы продолжать проверять значение, и когда оно вернется к true, вы могли бы начать воспроизведение снова(для этого потребуется несколько вызовов между методами, но это выполнимо).

Если вы хотите сохранить позицию, в которой она перестала воспроизводиться, вы можете постоянно сохранять позицию в потоке бегунов в длинном поле, я не думаю, что поток управления нуждается в доступе к этому (если вы не хотите отображать ее в поле, я думаю).

Краткий пример:

 public class Example {   static volatile boolean isPlaying;   public static void main(String[] args) throws InterruptedException {  //runner  Runnable runnable = () -gt; {  try {  Example.play();  } catch (InterruptedException ex) {  System.out.println("fail");  }  };  Thread thread = new Thread(runnable);  thread.start();   //control  Runnable runnable2 = () -gt; {  Example.stopButton();  };  Thread thread2 = new Thread(runnable2);  thread2.start();   Thread.sleep(5000);  Example.stopButton();   }   public static void play() throws InterruptedException {  isPlaying = true;  int i = 0;   while (isPlaying) {  //code to play music   System.out.println("playing - "   i);  i  ;  Thread.sleep(1000);  }   System.out.println("Out of loop, stopped playing");  }   public static void stopButton() {  synchronized (Example.class) {  isPlaying = false;  }  }  }  

Комментарии:

1. Спасибо, мне очень жаль, если это глупый вопрос, но куда мне поместить моих слушателей действий?

2. Я бы поместил их в класс, который отвечает за управление приложением (просто простота использования). Их не нужно разделять между потоками, поэтому, я думаю, они не нужны… Всегда старайтесь свести синхронизацию ezp к минимуму, так как это сопряжено с накладными расходами (очистка кэша процессора, чтение прямо из оперативной памяти, блокировка чтения и т. Д.).