簡體   English   中英

Thread.sleep()的意外行為

[英]Unexpected behaviour with Thread.sleep()

我構建了一個簡單的程序來播放一首歌。

import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import java.io.File;
import javax.swing.*;
import java.awt.*;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.application.Platform;
import javafx.scene.Group; 

public class Fade {
    private void initAndShowGUI() {
        // This method is invoked on Swing thread
        JFrame frame = new JFrame("FX");
        final JFXPanel fxPanel = new JFXPanel();
        frame.add(fxPanel);
        frame.setVisible(true);

        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                initFX(fxPanel);
            }
        });
    }

    private void initFX(JFXPanel fxPanel) {
    // This method is invoked on JavaFX thread
        Group root = new Group(); 
        Scene scene = new Scene(root, 500, 500, true);
        fxPanel.setScene(scene);

        try {
            String bip = new File("./Sound/Welcome To The Show - L1-5.mp3").toURI().toString();
            Media hit = new Media(bip);
            MediaPlayer mediaPlayer = new MediaPlayer(hit);
            mediaPlayer.play();

            Thread.sleep(10000);
            System.out.println("Fade");
        } catch (Exception e) {
            System.out.println("Exception");
            System.out.println(e);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Fade().initAndShowGUI();
            }
        });
    }
}

但是,當運行此代碼時, Thread.sleep(10000)在歌曲開始播放之前運行而不是開始播放的歌曲,然后10秒后fade打印到控制台。 我該如何解決這個問題?

您正在阻止JavaFX應用程序線程,因此它無法執行其正常工作(可能包括處理媒體播放器的指令以啟動),直到您的方法完成。 您永遠不應該阻止此線程,因為它可以保證UI不響應。

在JavaFX中實現暫停的最簡單方法是使用PauseTransition

MediaPlayer mediaPlayer = new MediaPlayer(hit);
mediaPlayer.play();

// never do this:
//Thread.sleep(10000);

PauseTransition pause = new PauseTransition(Duration.millis(10000));
pause.setOnFinished(e -> {
    System.out.println("Fade");
});
pause.play();

(順便說一句,我認為你的真實應用程序有一些理由混合swing和JavaFX。否則你應該把它變成一個純JavaFX應用程序。)

MediaPlayer上操作是異步的。 這解釋了為什么在實際音樂開始之前打印"Fade" 文檔

MediaPlayer的操作本質上是異步的。 玩家不准備立即響應命令,直到其狀態轉換為MediaPlayer.Status.READY ,這實際上通常在媒體預滾動完成時發生。 但是,在狀態為READY之前對玩家提出的某些請求將在輸入該狀態時生效。 這些包括在READY轉換之前調用play()而不調用pause()stop() ,以及設置autoPlaybalancemuteratestartTimestopTimevolume屬性中的任何一個。

您可以通過輪詢其狀態來控制玩家是否實際正在玩游戲。 play() (強調我的):

開始播放媒體。 如果之前暫停,則播放將在暫停時恢復。 如果停止播放,則從startTime開始播放。 實際播放時,狀態將設置為MediaPlayer.Status.PLAYING

要在播放器開始播放時注冊回調,您可以通過添加更改偵聽器或通過調用setOnPlaying(runnable)直接設置事件處理程序來掛接到onPlayingProperty

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM