如何从不同的动作监听器调用同一个线程

Posted

技术标签:

【中文标题】如何从不同的动作监听器调用同一个线程【英文标题】: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 中的停止按钮时,我不知道如何停止我的音乐(我在调用它时打印出该方法)但不会停止音乐,这就是为什么我认为停止我的音乐我需要在播放按钮运行的同一线程中调用我的方法,这是正确的吗?我怎么做?谢谢。

【问题讨论】:

【参考方案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 读取,阻塞读取等...)

以上是关于如何从不同的动作监听器调用同一个线程的主要内容,如果未能解决你的问题,请参考以下文章

从 vuex 模块中监听动作/突变

如何将始终从特定线程调用其回调的侦听器包装到符合 subscribeOn 定义的调度程序的 Observable 中?

Java:使用动作监听器在该类的对象上调用另一个类中的函数

另一个组件如何在 react/redux 中监听另一个组件的动作?

JAVA,如何实现点击不同菜单项后,面板显示不同内容用以实现不同功能?

h:commandLink 动作和 f:ajax 监听器的调用顺序