gpt4 book ai didi

java - 如何停止一次多次播放 mp3 文件?

转载 作者:行者123 更新时间:2023-11-30 11:32:32 27 4
gpt4 key购买 nike

我正在尝试通过按下按钮或从列表中选择(我已成功管理)来播放 mp3 文件。但是,我似乎无法在同一按钮按下时停止多次播放歌曲。

我想做的是在新线程中播放歌曲,在线程关闭之前再次禁止播放歌曲,然后再次播放。

我的代码如下:

public class SoundFactory {

private Player player;
private static boolean running = false;

private String getFile(String name) {
String f = "sound" + File.separator + name + ".mp3";
return f;
}

public void playMP3(String name) {


if (!running) {
running = true;

try {
FileInputStream fis = new FileInputStream(getFile(name));
BufferedInputStream bis = new BufferedInputStream(fis);
player = new Player(bis);
} catch (Exception e) {
System.out.println("Problem playing file " + name);
System.out.println(e);
}

// run in new thread to play in background
new Thread() {
public void run() {
try {
player.play();
} catch (Exception e) {
System.out.println(e);
}
}
}.start();
//running = false;
}
}


public void close() {
if (player != null) player.close();
}

文件通过以下方式播放:

    SoundFactory sf = new SoundFactory();
sf.playMp3("song name");

在 JButton 上点击

我是线程的新手,所以如果这有一个明显的解决方案,我提前道歉!

最佳答案

在我看来,您同时触发了多个点击事件,而不是一个。一点日志记录应该可以验证这一点。您的方法对竞争条件是完全开放的。

这两个事件可以非常接近,以至于当一个事件检查正在运行时,它会看到 !running 为真。在此之前,可以执行 running = true,第二个事件也将 !running 视为 true 并进入 if 子句。然后他们都将 running 设置为 true 并生成一个线程来播放 mp3。

您需要做的是使您的方法同步。

public synchronized void playMP3(String name)

http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

If count is an instance of SynchronizedCounter, then making these methods synchronized has two effects:

  • First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
  • Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.

为了澄清我最后的评论,这里有一个测试程序显示了 running = false 应该放在哪里。

public class Test {

public static boolean running = false;

public synchronized void runner() {
if(!running) {
running = true;
System.out.println("I'm running!");
new Thread() {
public void run() {
for(int i=0; i<10000; i++) {} // Waste some time
running = false; // This is only changed once the thread completes its execution.
}
}.start();
} else {
System.out.println("Already running.");
}
}

public static void main(String[] args) {
Test tester = new Test();
tester.runner();
tester.runner(); // The loop inside the Thread should still be running so this should fail.
for(int i=0; i<20000; i++) {} // Waste even more time.
tester.runner(); // The loop inside the Thread should be done so this will work.
}
}

输出:

I'm running! 
Already running.
I'm running!

自从我使用 Swing 以来已经有好几年了,并且忘记了它的事件调度程序是单线程的。所以你的问题比竞争条件更有可能。从一开始就编写线程安全的东西仍然没有坏处,因为它会让您习惯并以这种方式思考。

关于使用同步方法的明确警告...如果您的方法中只有一小部分需要同步,那么性能可能会很糟糕。在这种情况下,您的整个方法都需要是线程安全的。

如果只有一小部分需要线程安全,则需要使用同步块(synchronized block)。

每个实例线程安全:

public class myClass {
public void myFunc() {
// bunch of code that doesn't need to be thread safe.
synchronized(this) {
// Code that needs to be thread safe per instance
}
// More code that doesn't need thread safety.
}
}

在所有实例中都是线程安全的。

public class myClass {
static Object lock = new Object();
public void myFunc() {
// bunch of code that doesn't need to be thread safe.
synchronized(lock) {
// Code that needs to be thread safe across all instances.
}
// More code that doesn't need thread safety.
}
}

静态方法中的线程安全。

public class myClass {
public static void myFunc() {
// bunch of code that doesn't need to be thread safe.
synchronized(MyClass.class) {
// Code that needs to be thread safe.
}
// More code that doesn't need thread safety.
}
}

可能比您想要的信息多得多,但我已经多次看到线程编程的教学如此糟糕。

关于java - 如何停止一次多次播放 mp3 文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16615581/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com