【问题标题】:how to call on the same thread from a different action listener如何从不同的动作监听器调用同一个线程
【发布时间】:2022-01-09 02:40:31
【问题描述】:

我正在为音乐播放器制作 GUI 我有 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 = () -> {
             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();

            }
       };

我还有一个暂停按钮可以暂停音乐。我的问题是,当我单击它执行的 GUI 中的停止按钮时,我不知道如何停止我的音乐(我在调用它时打印出该方法)但不会停止音乐,这就是为什么我认为停止我的音乐我需要在播放按钮运行的同一线程中调用我的方法,这是正确的吗?我怎么做?谢谢。

【问题讨论】:

    标签: java multithreading user-interface awt actionlistener


    【解决方案1】:

    您不需要调用与运行线程中相同的方法,您可以在“控制”线程上的同步方法中使用共享的“易失性”布尔值。

    让我们将这个布尔值命名为“isPlaying”; 然后,您将在运行线程中经常检查此布尔值的值。 然后在控制器类中,如果您希望 Runner 线程停止播放,您可以将此布尔值更改为 false,然后您可以继续检查该值,当它返回 true 时,您可以开始再次播放(它需要在方法之间进行一些调用,但它是可行的)。

    如果你想保存它停止播放的位置,你可以在 Runner 线程中不断地将该位置保存在一个长字段中,我认为控制线程不需要访问它(除非你想要将其显示在我猜的字段中)。

    简短示例:

    public class Example {
    
        static volatile boolean isPlaying;
    
        public static void main(String[] args) throws InterruptedException {
            //runner
            Runnable runnable = () -> {
                try {
                    Example.play();
                } catch (InterruptedException ex) {
                    System.out.println("fail");
                }
            };
            Thread thread = new Thread(runnable);
            thread.start();
    
            //control
            Runnable runnable2 = () -> {
                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;
            }
        }
    
    }
    

    【讨论】:

    • 谢谢,如果这是一个愚蠢的问题,我很抱歉,但是我应该把我的动作监听器放在哪里?
    • 我会将它们放在负责控制应用程序的类中(只是易于使用)。它们不需要在线程之间共享,所以我猜不需要 volatile... 总是尝试将同步同步到最低限度,因为它有开销成本(刷新 cpu 缓存,直接从 ram 读取,阻塞读取等...)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-19
    相关资源
    最近更新 更多