强制调用runOnUiThread发布进度时回调全部滞后的问题咨询
问题根源
runOnUiThread属于异步投递接口,调用后仅会将onProgressUpdate任务插入主线程消息队列就直接返回,不会同步等待主线程执行该任务。- 你的10万次for循环执行速度极快,全程仅需几毫秒,在此期间主线程没有抢到CPU时间片执行队列中的任务,所有的
### INNER ###会先被打印完毕,等后台线程跑完循环后,主线程才会批量执行队列中所有的进度更新任务,因此出现你看到的输出顺序。 - 你调整
synchronized块没有效果,是因为只要onProgressUpdate中没有对同一个this对象加锁,锁逻辑不会影响主线程任务的执行时机,自然解决不了顺序问题。
解决方法
方案1:模拟AsyncTask的常规进度更新效果
如果只需要视觉上的穿插输出,在每次投递进度任务后让后台线程短暂休眠,让出CPU时间片给主线程执行即可:
synchronized (this) { for (int i = 0; i < 100000; i++) { if (i % 100 == 0) { System.out.println("### INNER ### "); activity.runOnUiThread(this::onProgressUpdate); // 休眠10ms,给主线程留执行窗口 try { Thread.sleep(10); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } }
方案2:严格保证执行顺序
如果业务要求必须等本次进度更新执行完再继续后台任务,可以用CountDownLatch做同步等待:
synchronized (this) { for (int i = 0; i < 100000; i++) { if (i % 100 == 0) { System.out.println("### INNER ### "); CountDownLatch latch = new CountDownLatch(1); activity.runOnUiThread(() -> { onProgressUpdate(); latch.countDown(); }); // 阻塞等待主线程执行完进度更新 try { latch.await(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } }
内容的提问来源于stack exchange,提问作者Luis A. Florit
相关产品推荐
相关产品推荐

