简体   繁体   English

无法停止线程

[英]Can't stop thread

I have these two methods for creating and stopping a thread. 我有两种创建和停止线程的方法。 However the thread still keeps running, even after the first method is called. 但是,即使在调用第一个方法之后,线程仍然保持运行状态。 (I'm creating an object of the class and calling them from another class). (我正在创建该类的对象,并从另一个类中调用它们)。

private Thread thread;

public void stopAlarm() {
    Log.i(LOG_TAG, "stopAlarm called");
    sendAlarm = false;
    if (!thread.equals(null)) {
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}


public void triggerAlarm() {
    Runnable alarmTest = new Runnable() {
        @Override
        public void run() {
            while (sendAlarm) {
                Log.i(LOG_TAG, String.valueOf(sendAlarm));
            }
        }
    };
    thread = new Thread(Test);
    thread.start();
}

When stopAlarm is called the thread is always null, although it is called after triggerAlarm is called (thread is running). 调用stopAlarm时,线程始终为空,尽管在调用triggerAlarm(线程正在运行)之后调用该线程。

Depending on your OS you may find making your thread volatile may fix this. 根据您的操作系统,您可能会发现使线程不稳定可以解决此问题。

private volatile Thread thread;

However - there are better ways to do this. 但是-有更好的方法可以做到这一点。 One very useful one is using a small (just one entry) BlockingQueue which is poll ed by the running thread. 一种非常有用的方法是使用一个很小的(仅一个条目) BlockingQueue ,它由正在运行的线程poll

// Use a BlockingQueue to signal the alarm to stop.
BlockingQueue<String> stop = new ArrayBlockingQueue<>(1);

public void stopAlarm() {
    stop.add("Stop");
}


public void triggerAlarm() {
    new Thread(() -> {
        try {
            while (stop.poll(1, TimeUnit.SECONDS) == null) {
                // Stuff
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }).start();
}

Clearly you will have to manage edge cases like where someone calls stopAlarm when no alarm is running. 显然,您将不得不处理一些stopAlarm情况,例如当没有警报运行时有人呼叫stopAlarm

Your problem is caused by thread scope. 您的问题是由线程范围引起的。 Thread scope is created when you create a thread with same variables in the scope but you can't change these variables from outside world. 当您在范围内创建具有相同变量但无法从外部更改这些变量的线程时,便会创建线程范围。 Best practice for managing runnables in android is to use Handler . 在android中管理可运行对象的最佳实践是使用Handler

Handler handler = new Handler();
Runnable alarmTest = new Runnable() {
    @Override
    public void run() {
        Log.i(LOG_TAG, String.valueOf(sendAlarm));
        handler.post(alarmTest, 5000); //wait 5 sec and run again
        //you can stop from outside
    }
};

after definitions, in order to start the runnable: 在定义之后,为了启动可运行对象:

handler.post(alarmTest,0); //wait 0 ms and run

in order to stop the runnable: 为了停止可运行:

handler.removeCallbacks(alarmTest);

EDIT: wait statement with loop 编辑:带有循环的等待语句

EDIT: Complete solution 编辑:完整的解决方案

Handler handler = new Handler();
Runnable alarmTest = new Runnable() {
    @Override
    public void run() {
        Log.i(LOG_TAG, String.valueOf(sendAlarm));
        handler.post(alarmTest, 5000); //wait 5 sec and run again
        //you can stop from outside
    }
};

public void stopAlarm() {
    Log.i(LOG_TAG, "stopAlarm called");
    handler.removeCallbacks(alarmTest);
}


public void triggerAlarm() {
    handler.post(alarmTest,0); //wait 0 ms and run
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM