【问题标题】:Interrupting a thread from a method从方法中断线程
【发布时间】:2020-02-27 08:33:37
【问题描述】:

我想用 interrupt() 方法中断一个线程,但是我遇到了我无法解释的行为。

如代码所示,从 MainActivity 调用 worker 方法 cancel() 不能中断线程,而调用 workerThread.interrupt() 可以。

如果 worker 自己调用 cancel(),它就会中断。

除非当前线程正在中断自己,这总是允许的,否则调用该线程的 checkAccess 方法,这可能会导致抛出 SecurityException。

我认为这可能是一个安全异常,导致 UIThread 试图中断 workerThread,但它没有被抛出。如果调用workerThread.interrupt()时也应该抛出?


Worker.java

package com.example.threadapp;
public class Worker implements Runnable {

    public void cancel() {
        Log.d("Threading", "call Thread.currentThread().interrupt()");
        try {
            Thread.currentThread().interrupt();
        } catch (SecurityException e) {
            e.printStackTrace();
            Log.d("Threading", "SecurityException while interrupting");
        }

    }

    @Override
    public void run() {
        //
        while(!Thread.currentThread().isInterrupted()) {
            Log.d("Threading", "Worker alive");
            try {
                Thread.currentThread().sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
                Thread.currentThread().interrupt();
                cancel();
            }
            //cancel(); //interrupts thread
            //Thread.currentThread().interrupt(); //interrupts thread

        }
        //
        Log.d("Threading", "Worker Thread closing");
    }
}


MainActivity.java

public class MainActivity extends AppCompatActivity {

    private Worker worker;
    private Thread workerThread;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        worker = new Worker();
        workerThread = new Thread(worker);
        workerThread.start();

        (new Handler(Looper.getMainLooper())).postDelayed(new Runnable() {
            @Override
            public void run() {
                Log.d("Threading", " call worker.cancel()");
                worker.cancel(); //doesn't interrupt thread
                //workerThread.interrupt(); //interrupts thread
            }
        }, 10000);
    }
}

【问题讨论】:

    标签: java android multithreading


    【解决方案1】:

    worker.cancel 在主线程中被调用。因此,cancel方法内的Thread.currentThread()返回主线程,因此interrupt方法被主线程调用。在这种情况下,您不会中断工作线程。

    【讨论】:

    • 但是workerThread.interrupt()不也是从主线程调用的吗?
    • 中断方法在工作线程内切换一个标志变量。因此,当您调用 isInterrupted 时,它会返回该值。因此,您在哪里调用它并不重要。另一方面,当您调用 mainThread.interrupt 时,它会切换主线程的标志变量。在这种情况下,isInterrupted 将始终返回 false,因为它不知道来自主线程的值。
    • 如果只是一个标志,从哪里设置都没有关系,为什么(从MainThread调用)worker.cancel()不会中断线程和workerThread.interrupt( );会吗?
    • 记得 while 循环是在工作线程上运行的,对吧?当您调用workerThread.start() 时,就会发生这种情况。因此,当您调用 Thread.currentThread.isInterrupted 时,实际上是在调用 workerThread.isInterrupted。该方法要求 workerThread 中变量的值。当您调用workerThread.interrupt 时,该变量已更改。因此,如果您在主线程中调用它并不重要,您将能够更改该变量。当您调用调用worker.cancel时发生的mainThread.interrupt时,isInterrupted所需的变量没有改变
    • 相反,它更改了 mainThread 中的变量。请记住,所问的是workerThread 中的变量。如果你想检查你在哪个线程,你可以使用Thread.currentThread.getName。你会看到cancel方法里面的代码确实是在主线程中运行的。
    猜你喜欢
    • 1970-01-01
    • 2019-07-01
    • 1970-01-01
    • 2015-10-31
    • 2017-12-02
    • 1970-01-01
    • 2015-11-20
    • 2019-11-23
    • 2023-03-25
    相关资源
    最近更新 更多