【Android】小白进阶之如何保证service不被杀死和如何结束线程基础浅析
发布日期:2021-05-08 10:09:25 浏览次数:22 分类:原创文章

本文共 3138 字,大约阅读时间需要 10 分钟。

1、保证 service 不被杀掉


StartCommond 的几个常量参数简介:


a、START_STICKY


在运行 onStartCommand 后 service 进程被 kill 后将保留在开始状态,但是不保留传入的intent。
之后 service 就会再次尝试重新创建,因为保留在开始状态,在创建 service 后将保证调用 onstartCommand,如果没有传递任何开始命令给 service,那将获取到 null 的 intent。


b、START_NOT_STICKY


在运行 onStartCommand 后 service 进程被 kill 后,并且没有新的 intent 传递给它。
Service 将移出开始状态,并且直到新的方法(startService)调用才重新创建。
因为如果没有传递任何未决定的 intent 那么 service 是不会启动,也就是期间 onstartCommand 不会接收到任何 null 的 intent。


c、START_REDELIVER_INTENT


在运行 onStartCommand 后 service 进程被 kill 后,系统将会再次启动 service,并传入最后一个 intent 给 onstartCommand。
直到调用 stopSelf(int) 才停止传递 intent。如果在被 kill 后还有未处理好的 intent,那被 kill 后服务还是会自动启动。因此 onstartCommand 不会接收到任何 null 的 intent。


@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {    flags = START_STICKY;    return super.onStartCommand(intent, flags, startId);}

2、如何结束线程


a、stop 强制停止


Android 的线程类本身提供了一些公共方法去结束线程,但不安全不建议使用


final void stop();


b、线程里的 run 函数执行完后线程会自行销毁


c、手动停止


在 run 里设置标志先停止运行,再调用 Thread.interrupt()


注:在 run 没有停止时调用 Thread.interrupt() 是没有效果的


示例:


a、加入一个成员变量, 在程序的循环里轮流去检查这个变量,变量变化时,就会退出这个线程


public class StopThread extends Thread {    private boolean _run = true;    public void stopThread(boolean  run) {         this._run = !run;    }       @Override   public void  run() {        while(_run) {           // 相应处理        }    }}

b、方法 a 虽然可以取消线程,但是在有阻塞线程语句的时候会存在问题


比如设计到 Socket 的阻塞语句,虽然 java 提供异步 io 但是异步 io 是在程序里不断去查询有没有消息,耗电量较大


Java interrupt()方法且该方法是安全的,该方法可以将阻塞的线程唤醒过来,但不能将非阻塞的线程中断


while(!this.isInterrupted()) {    // 相应处理                  }public static void main(String[] args) {    StopThread thread=new StopThread();    thread.start();    try {        Thread.sleep(1000);    } catch (InterruptedException e) {            e.printStackTrace();    }            thread.interrupt();    System.out.println(interrupt);}

c、Android 在自己的 Api 中加入了 Process 类,可以直接结束进程,也就是当前线程所在的 JVM


final static void killProcess(int pid)


其中 pid 可以通过 Process.mypid() 获取,但这样终结的是整个程序


如果该线程处在不可中断状态下,就是没有调用上述 api,那么 java 只是设置一下该线程的 interrupt 状态,其他事情都不会发生,如果该线程之后会调用行数阻塞 API,那到时候线程会马会上跳出,并抛出 InterruptedException,接下来的事情就跟第一种状况一致了。如果不会调用阻塞 API,那么这个线程就会一直执行下去。


readCacheThread = new Thread(){    public void run() {               try {            Method getPackageSizeInfo = pm.getClass().getMethod(                    "getPackageSizeInfo", String.class,                    IPackageStatsObserver.class);            for (AppInfoItem item : installedApp) {                 sleep(1); // interrupt后会抛异常,这样就可以提前结束线程                getPackageSizeInfo.invoke(pm, item.packageName, pkgsizeobserver);            }            for (AppInfoItem item : systemApp) {                sleep(1);                getPackageSizeInfo.invoke(pm, item.packageName, pkgsizeobserver);            }                 } catch (Exception e) {                // TODO: handle exception                e.printStackTrace();                return;        }              };};readCacheThread.start();在需要中断线程的地方调用:if(readCacheThread != null && readCacheThread.isAlive()){    readCacheThread.interrupt();}

 


refer:


https://blog.csdn.net/mad1989/article/details/22492519
https://blog.csdn.net/lyf_007217/article/details/8542133


 

上一篇:【Android】小白进阶之单例模式浅析
下一篇:【Android】小白进阶之如何为产品设计超时监控机制

发表评论

最新留言

网站不错 人气很旺了 加油
[***.192.178.218]2025年03月23日 02时12分48秒