Java 从正在运行的线程调用方法

Java 从正在运行的线程调用方法,java,multithreading,methods,runnable,Java,Multithreading,Methods,Runnable,所以我正在尝试制作一个音乐播放器,它运行在一个单独的线程上。我希望在Player类(实现Runnable)中有暂停、播放和转到next/prev歌曲的方法。若我调用线程的内部方法,它还会在单独的线程上运行吗?一切都正常工作,但我对线程还是新手,所以我不确定这是否是一个好的实践。有人能解释一下吗 class Player implements Runnable, OnCompletionListener { public static final String TAG = "Player"

所以我正在尝试制作一个音乐播放器,它运行在一个单独的线程上。我希望在Player类(实现Runnable)中有暂停、播放和转到next/prev歌曲的方法。若我调用线程的内部方法,它还会在单独的线程上运行吗?一切都正常工作,但我对线程还是新手,所以我不确定这是否是一个好的实践。有人能解释一下吗

class Player implements Runnable, OnCompletionListener {
    public static final String TAG = "Player";
    private MediaPlayer mp;
    private boolean isPlaying = false;
    private SongsManager sm = null;
    private ArrayList<HashMap<String, String>> songsList = new ArrayList<HashMap<String, String>>();
    private int currentSongIndex = 0;

    public Player(int currentSongIndex){
        mp = new MediaPlayer();
        mp.setOnCompletionListener(this);
        sm = new SongsManager();
        songsList = sm.getSongList();
        this.currentSongIndex = currentSongIndex;
    }

    @Override
    public void run() {
        try{
            mp.reset();
            mp.setDataSource(songsList.get(currentSongIndex).get(SongsManager.KEY_PATH));
            mp.prepare();
            mp.start();
            isPlaying = true;
        } catch (IllegalArgumentException e){
            e.printStackTrace();
        } catch (IllegalStateException e){
            e.printStackTrace();
        } catch (IOException e){
            e.printStackTrace();
        }
    }

    public synchronized void pause() {
        if (isPlaying){
            if (mp != null){
                mp.pause();
                isPlaying = false;
            }
        }
    }

    public synchronized void play() {
        if (!isPlaying){
            if (mp != null){
                mp.start();
                isPlaying = true;
            }
        }
    }
    ...
}
然后从另一个线程调用player.pause(),然后调用player.play(),那么该播放器是否仍在另一个线程上运行

若我调用线程的内部方法,它还会在单独的线程上运行吗

不,线不是魔法。当您调用一个方法时,您正在使用当前线程调用该方法。要分叉线程,实际上必须创建一个线程对象(或执行器服务)并启动它。然后它调用
run()
,等等

因此,如果您调用了
player.pause()
,您将从当前线程(可能是“主”线程)调用pause。您的
playerThread
将在后台执行其他操作。
pause()
方法之所以是
synchronized
,是因为您可以从外部线程和
playerThread
执行所有操作,而不必重叠。这还意味着多个线程可以测试和设置
isPlaying
布尔值,其他线程将看到更新


您最有可能从。

开始
run()
方法的内容是在单独的线程上执行的。任何调用包含
run()
的类的方法的操作都将在其自己的线程上执行该方法。因此,您必须确保任何数据访问都是线程安全的。

好的,谢谢;因此,如果在同步方法中不使用mp.pause()/.start(),我只调用了Player.pause()和Player.start()方法,然后创建了一个新线程(Player,TAG.start()),这将实现我的目标?看起来你对@ChrisMcJava感到困惑。如果您正在调用
Player.start()
,则
start()
需要是
static
。当您在
静态
方法上同步时,您正在
Player.class
对象上同步,这可能不是您想要的。对不起,我的错误,我不是指Player.start();请允许我重新表述一下:那么,在播放器被实例化之后,创建了一个新的播放器线程(线程playerThread=new thread(player,TAG).start();),然后从主ui线程调用player.pause(),如果我省略了player.play()方法,创建了一个新线程(线程playerThread=new thread(player,TAG).start())当从UI中按下播放按钮时?我想这会管用的
Player player = new Player(0);
playerThread = new Thread(player, Player.TAG);
playerThread.start();