Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/388.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在后台线程内终止长时间运行的任务_Java_Android_Multithreading_Rx Java_Rx Android - Fatal编程技术网

Java 在后台线程内终止长时间运行的任务

Java 在后台线程内终止长时间运行的任务,java,android,multithreading,rx-java,rx-android,Java,Android,Multithreading,Rx Java,Rx Android,我有一个压缩图像的任务,它在图像中使用许多循环: 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

我有一个压缩图像的任务,它在图像中使用许多循环:

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 
                     }
                 }
             }
         }
     }
}
或者在后台工作线程中运行

TaskExecutor.queueRunnable(new Runnable() {
    @Override
    public void run() {
        writeCompressedData();
    }
});
问题是:当接收到无效输入时,此方法有时会出错并导致无限循环。在这种情况下,它将永远运行,即使当设备的屏幕关闭时,也会伤害CPU,这会增加设备的温度(如果我使用工作线程,它还会阻止等待队列中的其他任务)

我想我需要设置一个超时来终止长时间运行的任务。在普通Java线程中实现这一点的最佳方法是什么?RxJava支持它吗



我知道我需要修复的是“错误”的方法,而不仅仅是终止它。但是对于大型应用程序,很难控制其他开发人员的代码,我需要做的第一件事就是避免影响用户。

您可以使用Java
ExecutorService
Future
来解决此问题。看看这个。

更好的方法是在不同的进程中运行这样的代码。即使进程崩溃,主进程也将不受影响

您需要某种形式的协同取消,比如在一个或多个嵌套循环中检查
Thread.currentThread().isInterrupted()

for (/* ... */) {
    if (Thread.currentThread().isInterrupted()) return;

    for (/* ... */) {

        if (Thread.currentThread().isInterrupted()) return;

        for (/* ... */) {
            // the tightest loop
        }             
    }
}
然后在运行该方法时,保持
线程
/
未来
并调用
中断
/
取消(true)

在RxJava中,这看起来像这样:

new Thread(new Runnable() {
    @Override
    public void run() {
        writeCompressedData();
    }
});
backgroundDisposable = Completable.fromAction(() -> method())
.subscribeOn(Schedulers.io()) // dedicated thread recommended
.observeOn(AndroidSchedulers.mainThread())
.subscribe(() -> { /* done */ }, e -> { /* error */ });

// ...
backgroundDisposable.dispose();

我的方法是使用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");
                    }
                });
    }
private void timeOutObserver(){
创建(新的ObservableOnSubscribe(){
@凌驾
公共无效订阅(可观测发射器){
发射器.onNext(“A”);
}
})
.超时(5000,时间单位为毫秒)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.订阅(新观察员){
@凌驾
认购的公共无效(一次性d){
Log.d(“-@-”,“认购”);
}
@凌驾
public void onNext(字符串s){
Log.d(“-@-”,“下一个”+s);
}
@凌驾
公共无效申报人(可丢弃的e){
Log.d(“-@-”,e.getLocalizedMessage());
}
@凌驾
未完成的公共空间(){
Log.d(“-@-”,“完成时”);
}
});
}

有关超时运算符的更多操作,请参阅,

,但这将导致上下文切换成本。如果可能,您可以使用前台服务。它们的设计目的是让用户意识到某些进程正在后台运行,并在不再需要它时选择停止它。仅仅使用某种超时对我来说似乎是一个巨大的妥协。因为这只是一个小/快速的任务(只有当错误变大时),所以启动新服务对我来说似乎太大了。@nhoxbypass请分享你最终是如何做到这一点的,同时尝试rx方法shared@nhoxbypass在你的例子中,为了让这个例子起作用,在压缩代码成功的情况下更换发射器,默认情况下,如果在规定的时间内没有发射,它将抛出错误并停止执行,同样重要的是根据平台微调超时,就像如果平台是android,超时将在ANR内抛出一样。
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");
                    }
                });
    }