有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何从异步线程返回值

我正在制作一个MediaPlayer来播放音频文件

当前在主线程上工作

 public boolean playFile(String path) {
    MediaPlayer mp = new MediaPlayer();
    mp.setAudioAttributes(AudioFocusManager.getPlaybackAttributes());
    try {
        mp.setDataSource(path);
        mp.prepare();
        mp.start();
        mp.setOnErrorListener((mp1, what, extra) -> {
            return true;
        });
        mp.setOnCompletionListener( mp1 -> {
        });
        return true;
    } catch (Exception e) {
        return false;
    }
}

但我想把它交给遗嘱执行人

    ExecutorService executor = Executors.newSingleThreadExecutor();
    executor.execute(() -> {

    });

一旦我将其移动到执行器,那么第二个和第三个返回将触发一个错误

Unexpected return value

playFile触发以下事件

Missing return statement

我试过使用AtomicReference

AtomicReference<Boolean> correctlyPlayed = new AtomicReference<>(false);
    //set up MediaPlayer
    ExecutorService executor = Executors.newSingleThreadExecutor();
    executor.execute(() -> {
        MediaPlayer mp = new MediaPlayer();
        mp.setAudioAttributes(AudioFocusManager.getPlaybackAttributes());
        try {
            mp.setDataSource(path);
            mp.prepare();
            mp.start();
            mp.setOnErrorListener((mp1, what, extra) -> {
                return true;
            });
            mp.setOnCompletionListener( mp1 -> {
            });
            correctlyPlayed.set(true);
        } catch (Exception e) {
            AudioFocusManager.releaseAudioFocus();
            correctlyPlayed.set(false);
        }
    });

    return correctlyPlayed.get(); 

但它总是触发false,这意味着它不会等待线程更新它

我怎么做呢


共 (2) 个答案

  1. # 1 楼答案

    execute方法需要Runnable,而Runnable不返回任何内容,这就是为什么会出现意外的返回值错误。 您不能像这样直接从单独的线程获取播放文件的返回值,但您使用AtomicReference的方法应该是可行的。 有一个布尔值的内置原子类型,AtomicBoolean,考虑使用它。p>

    尝试更改此选项:

    mp.setOnErrorListener((mp1, what, extra) -> {
        return true;
    });
    

    为此:

    mp.setOnErrorListener((mp1, what, extra) -> {
        correctlyPlayed.set(true);
    });
    

    此外,您可能需要同步代码以等待另一个线程在返回之前执行,为此,考虑检查一些信号量同步技术(例如,CurnDutLaCH),我建议您也阅读有关等待通知机制。正如您正确指出的,总是将false作为返回值的原因很可能是同步问题

  2. # 2 楼答案

    正如评论所说,使用executor#submit而不是executor#execute,这样您可以得到一个Future,您可以调用Future#get来获得结果:

           Future<Boolean> future = executor.submit(new Callable<Boolean>() {
                @Override
                public Boolean call() throws Exception {
                    // ...
                    return true;
                }
            });
            return future.get(); // block until get result