【发布时间】:2021-11-25 19:55:13
【问题描述】:
我正在尝试强制后台线程发布进度,例如 AsyncTask,但我失败得很惨。我不明白为什么它不起作用。
我这样开始后台线程:
new Thread(() -> {
doInBackground();
}).start();
在doInBackground() 内部,我有一个这样的循环:
...
synchronized (this) {
...
for (int i = 0; i < 100000; i++) {
...
if (i % 100 == 0) {
System.out.println("### INNER ### ");
activity.runOnUiThread(this::onProgressUpdate);
}
}
}
而onProgressUpdate() 很简单
onProgressUpdate() {
System.out.println("-------------");
}
我期望的是,对于每个### INNER ### ,我都会看到一个插入的-------------。然而,我首先看到所有### INNER ### ,然后是所有-------------。所以这条线
activity.runOnUiThread(this::onProgressUpdate);
在我想要的那一刻没有被执行。我尝试在各处添加和删除几个synchronized (this),但没有成功。
我做错了什么?
【问题讨论】:
-
IMO 这是一个正确的行为,输出取决于线程的执行。两种印刷品都以不同的线印刷。这就是为什么您看不到顺序执行的原因。当您向 UI 线程发布内容时,您当前的线程是空闲的并执行下一个 print ("### INNER ###) 语句。
-
我明白了。那么,如何解决这个问题呢?
-
您已经在 UI 线程上更新进度。确切的问题是什么?你永远无法确定主线程什么时候会执行你的runnable。
-
对不起,我以为我说得够清楚了。确切的问题是线程标题中的问题:强制runOnUiThread 获取
### INNER ###,然后是-------------,然后是### INNER ###,然后是-------------,依此类推。您的回答似乎是,除非我在同一个线程中执行所有操作(因此在执行doInBackground任务时阻止它),否则这是不可能的。但是,AsyncTask 中的publishProgress方法是如何执行此操作的呢? -
AsyncTask 在内部执行与您的代码非常相似的操作。它将作业发布到主处理程序上,该处理程序将作业传递到主 UI 线程。在此期间,异步操作永远不会受到干扰。您可以尝试类似 ``` val semaphore = Semaphore(1) val mainHandler = Handler(Looper.getMainLooper()) for (your logic) { try { semaphore.acquire() mainHandler.post { /* do your main ui work*/ semaphore.release() } } catch (e: Exception) {} } ```
标签: java android multithreading synchronization background-process