来自线程的方法调用在哪里运行?

Posted

技术标签:

【中文标题】来自线程的方法调用在哪里运行?【英文标题】:Where does a method call from a thread run? 【发布时间】:2021-01-23 10:06:56 【问题描述】:

这是我要写的代码

 void longRunningMethod() 
        new Thread(new Runnable() 
            @Override
            public void run() 
                //a time consuming task
                updateUi();
            
        ).start();
    
    public void updateUi()
         Collections.sort(playerArrayList, Collections.reverseOrder(new Comparator<Player>() 
                    @Override
                    public int compare(Player p1, Player p2) 
                        return Integer.valueOf(p1.getScore()).compareTo(p2.getScore());
                    
                ));
         adapter.notifyDataSetChanged();
         //some more code here
    

首先:当我从线程调用 updateUi() 时,它会在调用它的线程上运行(即 longRunningMethod() 的线程)还是会在主线程中运行?

其次:在代码中,我正在对自定义对象的数组列表进行排序,在主线程中运行它是否安全?还是我应该使用另一个线程?

我知道关于使用完成侦听器的任务实现,但我想在不同的线程上运行 updateUi 方法只是为了更安全。

【问题讨论】:

updateUi 没有在主线程上运行 旁注:如果您使用 java 8 或更新版本,您的比较器可以写得更简洁,例如:Comparator.comparing(Player::getScore).reversed() SideNote2:(其实整行甚至可以写成playerArrayList.sort(Comparator.comparing(Player::getScore).reversed()); 我建议看这个来理解线程。 docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html 【参考方案1】:

在线程中执行的任何操作,包括您调用的方法,仍将在正在运行的线程中执行,而不是在主线程中执行。因此,您实现 updateUI 方法的方式将使其仍在执行线程中运行。

在您的具体情况下,您似乎希望通过您的适配器通知 UI,因此您可以执行以下操作:

  public void updateUi()
    Collections.sort(playerArrayList, Collections.reverseOrder(new Comparator<Player>() 
        @Override
        public int compare(Player p1, Player p2) 
            return Integer.valueOf(p1.getScore()).compareTo(p2.getScore());
        
    ));

    // Notify the UI
    final Runnable runnable = () -> adapter.notifyDataSetChanged();
    new Handler(Looper.getMainLooper()).post(runnable);

接下来两行会通知 UI:

final Runnable runnable = () -> adapter.notifyDataSetChanged();
new Handler(Looper.getMainLooper()).post(runnable);

附带说明,如果您只是排序,并且列表很小,可以在几毫秒内完成,那么使用线程可能不是一个好的选择,您可以在 UI 中排序。或者,如果相反,实际上是一个很大的列表,可能会在排序时阻塞 UI,那么将这样的逻辑放在一个线程中并在完成时通知 UI 是正确的实现。

【讨论】:

以上是关于来自线程的方法调用在哪里运行?的主要内容,如果未能解决你的问题,请参考以下文章

期待来自另一个线程的 googlemock 调用

调用异步方法后,进程似乎没有回到 WPF 应用程序中的主线程

如何在没有任何中断的情况下运行线程

多线程

来自服务类的 Spring Boot 方法调用问题

C# 异步方法加await调用不就变成同步方法了吗