Java 如何启用以停止正在运行的代码?

Java 如何启用以停止正在运行的代码?,java,android,multithreading,runnable,Java,Android,Multithreading,Runnable,我在后台有一个很长的操作,比如上传东西、转换图像、音频、视频等。 如果用户请求完全停止操作,我想停止/取消它们 如何才能做到这一点?有这样的设计模式吗? 注意:有些正在运行的代码可以取消,有些则不能。我如何找到一个折衷方案 编辑:我应该说我希望操作立即停止。(我假设您已经在单独的线程中执行后台工作。) 基本上,您保留了一个共享的布尔标志,UI线程可以设置该标志,后台线程可以定期读取该标志。当旗帜上写着“停止”时,你停止:) 请注意,该标志应该是可变的,或者您应该使用锁,以确保后台线程肯定“看到”

我在后台有一个很长的操作,比如上传东西、转换图像、音频、视频等。 如果用户请求完全停止操作,我想停止/取消它们

如何才能做到这一点?有这样的设计模式吗?

注意:有些正在运行的代码可以取消,有些则不能。我如何找到一个折衷方案

编辑:我应该说我希望操作立即停止。

(我假设您已经在单独的线程中执行后台工作。)

基本上,您保留了一个共享的
布尔
标志,UI线程可以设置该标志,后台线程可以定期读取该标志。当旗帜上写着“停止”时,你停止:)

请注意,该标志应该是可变的,或者您应该使用锁,以确保后台线程肯定“看到”从UI线程写入的更改

它相对粗糙,感觉有点“手动”,但这意味着您不会因为操作中途中止而冒不稳定的风险,不像
Thread.stop()

(我假设您已经在一个单独的线程中执行后台工作)

基本上,您保留了一个共享的
布尔
标志,UI线程可以设置该标志,后台线程可以定期读取该标志。当旗帜上写着“停止”时,你停止:)

请注意,该标志应该是可变的,或者您应该使用锁,以确保后台线程肯定“看到”从UI线程写入的更改


它相对粗糙,感觉有点“手动”,但这意味着您不会因为操作中途中止而冒不稳定的风险,不像
Thread.stop()这样的方法

停止您正在使用的线程或异步任务或调用此。完成停止您正在使用的线程或异步任务或调用此。完成总结并扩展Jon所说的内容:

  • 您应该让线程知道它应该退出循环(volatile标志)
  • 如果希望线程退出阻塞状态,可以
    interrupt()
    线程
  • 您应该在
    run
    方法中处理
    InterruptedException
  • 当你被打断时,你应该优雅地退出(即完成你正在做的事情并清理)
一些代码:

private volatile bool _running;// volatile guarantees that the flag will not be cached

public void kill(){_running = false;}
public void run()
{
    while(_running)
    {        
        try
        {
            DoWork(); // you may need to synchronize here
        }
        catch(InterruptedException e)
        {
            // Handle e
        }
    }
}

总结并扩展Jon所说的内容:

  • 您应该让线程知道它应该退出循环(volatile标志)
  • 如果希望线程退出阻塞状态,可以
    interrupt()
    线程
  • 您应该在
    run
    方法中处理
    InterruptedException
  • 当你被打断时,你应该优雅地退出(即完成你正在做的事情并清理)
一些代码:

private volatile bool _running;// volatile guarantees that the flag will not be cached

public void kill(){_running = false;}
public void run()
{
    while(_running)
    {        
        try
        {
            DoWork(); // you may need to synchronize here
        }
        catch(InterruptedException e)
        {
            // Handle e
        }
    }
}

我的2美分。可以取消的任务。需要实现
cancelImpl()
runImpl()

import java.util.concurrent.CancellationException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

public abstract class CancelableTask extends Observable<CancelableTask>
        implements Runnable {
    private volatile boolean isStarted = false;
    private volatile boolean isCanceled = false;
    private volatile boolean isSuccess = false;
    private volatile Exception e;
    private volatile AtomicBoolean doneLock = new AtomicBoolean(false);
    protected final AtomicInteger progress = new AtomicInteger(0);

    public CancelableTask() {
    }

    @Override
    public final void run() {
        try {
            runUnsafe();
        } catch (Exception e) {
            Config.getLog().i("CancelableTask threw an exception", e);          
        }
    }

    public final void runUnsafe() throws Exception {
//      Config.getLog().d("Running cancelable task: " + toString());
        notifyObservers(this);
        isStarted = true;
        try {
            if (!isCanceled) {
                runImpl();
            }
        } catch (Exception e) {
            // Note: Cancel may throw exception
            if (doneLock.compareAndSet(false, true)) {
                this.e = e;
                notifyObservers(this);
                clearObservers();
                // Someone else should do something with the exception
//              Config.getLog().i("Failed cancelable task: " + toString(), e);
                throw e;
            }
            // Cancel got to the lock first but may NOT have yet changed the cancel flag.
            // Must throw cancellation exception.
        }
        if (doneLock.compareAndSet(false, true)) {
            isSuccess = true;
            progress.set(100);
            notifyObservers(this);
            clearObservers();
//          Config.getLog().d("Finished cancelable task: " + toString());
            return;
        }

        // The task was canceled but the isCanceled may not have been set yet.

        synchronized (doneLock) { // Waiting for the cancel to finish it's logic
        }

//      assert isCanceled; // Commented out because android crashes the app in assertion 
        // No need to notify here because cancel was already notified in
        // cancel method.
        // notifyObservers(this);
//      Config.getLog().d("Already canceled task: " + toString());
        throw new CancellationException("Canceled while running!");
    }

    protected abstract void runImpl() throws Exception;

    protected void cancelImpl() {}

    public final void cancel() {
        synchronized (doneLock) {
            if (doneLock.compareAndSet(false, true)) {
//              Config.getLog().i("Canceling cancelable task: " + toString());
                isCanceled = true;

                cancelImpl();

                notifyObservers(this);

                clearObservers();
            }
        }
    }

    public final boolean isCanceled() {
        return isCanceled;
    }

    public final boolean isSuccessful() {
        return isSuccess;
    }

    public final boolean isDone() {
        return doneLock.get();
    }

    public final boolean isStarted() {
        return isStarted;
    }

    public final Exception getError() {
        return e;
    }

    public int getProgress() {
        return progress.get();
    }

    /**
     * Observers will be cleared after the task is done but only after all of them are notified.
     */
    @Override
    public void addObserver(Observer<CancelableTask> observer) {
        super.addObserver(observer);
    }


//  protected void incrementProgress(int value) {
//      progress += value;
//  }
}
import java.util.concurrent.CancellationException;
导入java.util.concurrent.AtomicBoolean;
导入java.util.concurrent.AtomicInteger;
公共抽象类CancelableTask扩展了Observable
实现可运行{
私有易失性布尔值isStarted=false;
private volatile boolean isCanceled=false;
private volatile boolean issucess=false;
私有易失性异常e;
private volatile AtomicBoolean doneLock=新的AtomicBoolean(false);
受保护的最终AtomicInteger进度=新的AtomicInteger(0);
公共可取消任务(){
}
@凌驾
公开最终作废运行(){
试一试{
runUnsafe();
}捕获(例外e){
Config.getLog().i(“CancelableTask引发异常”,e);
}
}
public final void runsafe()引发异常{
//Config.getLog().d(“正在运行可取消的任务:+toString());
通知观察员(本);
IsStart=true;
试一试{
如果(!已取消){
runImpl();
}
}捕获(例外e){
//注意:取消可能引发异常
if(doneLock.compareAndSet(false,true)){
这个。e=e;
通知观察员(本);
clearObservers();
//其他人应该做一些例外的事情
//Config.getLog().i(“失败的可取消任务:+toString(),e”);
投掷e;
}
//Cancel首先到达锁,但可能尚未更改Cancel标志。
//必须抛出取消异常。
}
if(doneLock.compareAndSet(false,true)){
isSuccess=true;
进度。设定(100);
通知观察员(本);
clearObservers();
//Config.getLog().d(“已完成可取消任务:+toString());
返回;
}
//任务已取消,但可能尚未设置isCanceled。
已同步(doneLock){//等待取消完成其逻辑
}
//assert isCanceled;//已注释掉,因为android在断言中使应用程序崩溃
//无需在此通知,因为已在中通知取消
//取消方法。
//通知观察员(本);
//Config.getLog().d(“已取消的任务:+toString());
抛出新的CancellationException(“运行时已取消!”);
}
受保护的抽象void runImpl()引发异常;
受保护的void cancelImpl(){}
公开最终作废取消(){
同步(多尼洛克){
if(doneLock.compareAndSet(false,true)){
//Config.getLog().i(“取消可取消的任务:+toString());
isCanceled=true;
cancelImpl();
通知观察员(本);
clearObservers();
}
}
}
公共最终布尔值已取消(){