我有一个在后台运行的工作线程。在此工作线程上,我有一个名为syncWithUiThreadAndWait的方法。这是简化的代码:
function formatNumber(num) {
var check = Math.round(num * 100) / 100;
var rounded = Math.round(check);
if (rounded == check) {
return String(rounded);
}
return num.toFixed(2);
}
function formatNumberViaToFixed(num) {
return num.toFixed(2).replace(/\.00$/, "");
}
function test(num) {
var formatted = formatNumber(num);
var viaToFixed = formatNumberViaToFixed(num);
if (formatted == viaToFixed) {
console.log(num, "=>", formatted);
} else {
console.log(num, "=>", formatted, "ERROR: Should be", viaToFixed);
}
}
test(1.01);
test(1.43);
test(23.7);
test(1.200123);
test(1.000043);
test(1.007);
test(1.0007);
所以我的问题是:为什么有时这段代码正确运行,有时线程循环无法启动,并且收到“ WHY”异常?
编辑: 我决定添加一些说明,以使其更易于理解。 我想做的是与UI线程同步的线程。
.as-console-wrapper {
max-height: 100% !important;
}
”,一旦我“阻止”后台线程继续执行,该任务就会运行。 private void syncWithUiThreadAndWait(final Runnable codeToSync) {
if (looper == null)
throw new RuntimeException("Thread is not ready (Looper=null)");
if (looper != Looper.myLooper())
throw new RuntimeException("Called from wrong thread");
final boolean[] wasRun = {false};
new Handler(looper).post(new Runnable() {
// I use 'new Handler(looper).post' instead of direct call to make sure that this code will
// run 100% after Looper.loop() is called, because in some cases it can be called before Looper.loop
@Override
public void run() {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
synchronized (MyWorkerThread.this) {
// Synchronization to establishes a happens-before relationship
wasRun[0] = true;
looper.quit();
}
}
});
}
});
Looper.loop();
synchronized (MyWorkerThread.this) {
// Synchronization to establishes a happens-before relationship
if (!wasRun[0])
throw new RuntimeException("WHY!!!");
}
}
“阻塞”了我的后台线程new Handler (looper) .post (...);
上运行的代码的末尾,被调用来取消阻塞后台线程。答案 0 :(得分:0)
所以即使我仍然不知道为什么会这样。因此,如果有人可以解释,我会将其标记为正确答案。
但是我发现了使用Thread.sleep()而不是Looper.loop()的解决方法。威奇为我工作,可能更有效率:
private void syncWithUiThreadAndWait(final Runnable codeToSync) {
synchronized (this) {
if (thread == null)
throw new RuntimeException("Thread not ready");
if (Thread.currentThread() != thread)
throw new RuntimeException("Called from wrong thread");
}
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
codeToSync.run();
setPaused(false);
}
});
setPaused(true);
final long sleepStart = System.currentTimeMillis();
while (isPaused()) {
try {
Thread.sleep(200);
} catch (InterruptedException ignored) { }
if (sleepStart + TIMEOUT_IN_MILLISEC <= System.currentTimeMillis())
throw new RuntimeException("Timeout waiting for network response");
}
}
private synchronized boolean isPaused() {
return paused;
}
private synchronized void setPaused(boolean newValue) {
paused = newValue;
}