我有一个压缩图像的任务,其中使用了很多循环:
private void writeCompressedData() {
int i, j, r, c, a, b;
loat[][] inputArray;
for (r = 0; r < minBlockHeight; r++) {
for (c = 0; c < minBlockWidth; c++) {
xpos = c * 8;
pos = r * 8;
for (comp = 0; comp < jpegObj.numberOfComponents; comp++) {
inputArray = (float[][]) jpegObj.components[comp];
for (i = 0; i < jpegObj.VsampFactor[comp]; i++) {
for (j = 0; j < jpegObj.HsampFactor[comp]; j++) {
xblockoffset = j * 8;
yblockoffset = i * 8;
for (a = 0; a < 8; a++) {
for (b = 0; b < 8; b++) {
// Process some data and put to inputArray
}
}
// Encode Huffman block
}
}
}
}
}
}
我在这样的普通线程中运行此方法:
new Thread(new Runnable() {
@Override
public void run() {
writeCompressedData();
}
});
或在后台工作线程中运行
TaskExecutor.queueRunnable(new Runnable() {
@Override
public void run() {
writeCompressedData();
}
});
问题是:此方法有时会出错,并在收到无效输入时导致无限循环。在这种情况下,即使设备屏幕关闭,它也将永久运行并损坏CPU ,这会提高设备的温度(如果使用工作线程,它还会阻塞等待队列中的其他任务)。
我认为我需要设置超时以终止长时间运行的任务。在普通Java线程中实现此目标的最佳方法是什么? RxJava支持吗?
我知道我需要修复的是“错误的”方法,而不仅仅是终止它。但是对于大型应用程序而言,很难控制其他开发人员的代码,而我首先需要避免影响用户。
答案 0 :(得分:2)
您需要某种形式的协作取消,例如在一个或多个嵌套循环中检查Thread.currentThread().isInterrupted()
。
for (/* ... */) {
if (Thread.currentThread().isInterrupted()) return;
for (/* ... */) {
if (Thread.currentThread().isInterrupted()) return;
for (/* ... */) {
// the tightest loop
}
}
}
然后,当您运行该方法时,保持Thread
/ Future
并调用interrupt
/ cancel(true)
:
backgroundTask = new Thread(() -> method());
backgroundTask.start();
// ...
backgroundTask.interrupt();
backgroundFuture = executorService.submit(() -> method());
// ...
backgroundFuture.cancel(true);
在RxJava中,它看起来像这样:
backgroundDisposable = Completable.fromAction(() -> method())
.subscribeOn(Schedulers.io()) // dedicated thread recommended
.observeOn(AndroidSchedulers.mainThread())
.subscribe(() -> { /* done */ }, e -> { /* error */ });
// ...
backgroundDisposable.dispose();
答案 1 :(得分:1)
您可以将Java import jenkins.model.*
RunList[] myBuilds = Jenkins.instance.getAllItems()
.findAll{ it instanceof Job && it.getName() == {your job name} }
.collect { it.getBuilds().byTimeStamp({your start date}, {your end date} }
与超时一起使用,而ExecutorService
可以解决此问题。参见此Text editor to open big files。
答案 2 :(得分:0)
更好的方法是在不同的进程中运行此类代码。即使进程崩溃,主进程也不会受到影响。
答案 3 :(得分:0)
我的方法是使用 RxJava ,更具体地说是使用RxJava的 Timeout
运算符,这是代码的要点,5秒钟后,onError将之所以被称为是因为在过去5秒钟内没有发射任何物品,
private void timeOutObserver() {
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) {
emitter.onNext("A");
}
})
.timeout(5000, TimeUnit.MILLISECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.d("-@-", "subscribed");
}
@Override
public void onNext(String s) {
Log.d("-@-", "on next " + s);
}
@Override
public void onError(Throwable e) {
Log.d("-@-", e.getLocalizedMessage());
}
@Override
public void onComplete() {
Log.d("-@-", "on complete");
}
});
}
有关“超时”运算符的更多信息,请参见this,