来自线程的方法调用在哪里运行?
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 是正确的实现。
【讨论】:
以上是关于来自线程的方法调用在哪里运行?的主要内容,如果未能解决你的问题,请参考以下文章