#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 к минимуму, так как это сопряжено с накладными расходами (очистка кэша процессора, чтение прямо из оперативной памяти, блокировка чтения и т. Д.).