如何 return 来自异步线程的值

How to return a value from a async thread

我正在开发 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(() -> {

    });

一旦我将其移至执行程序,第二个和第三个 returns 就会触发错误

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,意味着它不等待线程更新它

我该怎么做?

execute 方法需要一个 Runnable 而 Runnable 不需要 return 任何东西,这就是为什么你会得到意外的 return 值错误。 您不能像这样直接从单独的线程获取播放文件的 return 值,但是您使用 AtomicReference 的方法应该有效。 布尔值有一个内置的原子类型 AtomicBoolean,请考虑改用它。

尝试改变这个:

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

为此:

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

此外,您可能希望在 returning 之前同步您的代码以等待其他线程执行,为此,请考虑检查一些信号量同步技术(例如 CountdownLatch),我建议您阅读也了解等待通知机制。正如您正确指出的那样,始终将 return 值设为 false 的原因很可能是同步问题。

如评论所说,用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