服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Android - 深入Android线程的相关问题解惑

深入Android线程的相关问题解惑

2021-01-17 16:52Android开发网 Android

本篇文章是对Android线程的相关问题进行了详细的分析介绍,需要的朋友参考下

一个应用只有一个线程
在默认情况下,更确切的讲一个进程中只有一个线程,这跟其他语言,比如c/c++,java等是一致。也就是说在android应用程序里面一个进程只有一个线程,所有组件都运行在一个线程里面!

当应用程序启动时,系统会为其创建一个进程,也会创建一个线程名字叫做main,所有其所属组件的创建,系统事件的处理,系统的回调等一切应用相关的事情都运行在此名叫main的线程中。此线程即为常说的主线程(main thread)。俗称的ui线程(ui thread)也是它,因为只有主线程可以操作ui相关的事情,所以有人把主线程也称作ui线程,但这并不是正确的说法,因为service所属的线程也可以操作toast,但是service并没有ui。为什么非主线程不能操作ui呢?因为对ui操作常常会引发系统的回调,所以如果允许第三线程来操作可能会引发系统回调的紊乱,进而会打乱整个框架的时序!
这里要特别注意的就是同一个进程中的所有组件运行在同一个线程中,activiy,service,boradcastreceiver和contentprovider都运行在主线程中。

最容易引起误解的就是service,文档和常识都会认为service是放在后台用于操作费时运算的,但是实则不然,如果你在service中做费时操作,同样会引发臭名昭著的anr(application not responding)。所以如果想把service当做一个server,必须在service用handlerthread或thread创建一个worker线程!
activity也是一样的,你startactivity()后,开启了一个新的activity,但它们都运行在同一个线程中,所以你还是不能在原activity中做费时操作!也即在调用startactivity()开启了一个新的activity后,或者在onpause(), onstop(), ondestroy()中做费时操作会引发anr。

对于contentprovider也是一样的,如果跟其他组件在同一进程内,那么调用contentresolver的方法会相当于直接调用contentprovider的方法。如果是在另外一个进程中,虽是通过ipc,但也是同步的,因为ibinder的同步的,也即调用contentresolver时会把调用者的进程挂起,等待contentprovider的进程操作结束,再把结果传给调用者进程!所以,如果contentprovider中有费时操作,或者会同步锁数据库等,也一定要注意anr的发生!
所以一定要记住:一个进程只有一个线程,所有组件都运行在主线程中。
因此,如果有费时操作,必须要创建worker线程!

深入Android线程的相关问题解惑

实例
下面有一个小实例,一个应用中有五个组件:2个activity,一个service,一个contentprovider和一个broadcastreceiver。在每个组件的方法中都有打印所属线程信息,另外对于activity,service和contentprovider如果做费时操作会引发anr,对于broadcastreceiver更是如此,这个大家都懂得的!

复制代码 代码如下:


public class activitydemo extends activity {
    private static final string tag = "activitydemo";
    private handler mmainhandler = new handler(new handler.callback() {
 public boolean handlemessage(message msg) {
     dumpthreadinfo();
     return false;
 }
    });

    @override
    protected void oncreate(bundle savedinstancestate) {
 dumpthreadinfo();
 super.oncreate(savedinstancestate);

 // add four buttons
 linearlayout layout = new linearlayout(getapplication());
 layout.setorientation(linearlayout.vertical);
 button startservice = new button(getapplication());
 startservice.settext("start a service");
 startservice.setonclicklistener(new view.onclicklistener() {
     public void onclick(view v) {
  intent i = new intent(getapplication(), servicedemo.class);
  startservice(i);
     }
 });
 layout.addview(startservice);
 button startanother = new button(getapplication());
 startanother.settext("start another activity");
 startanother.setonclicklistener(new view.onclicklistener() {
     public void onclick(view v) {
  intent i = new intent(getapplication(), anotheractivity.class);
  startservice(i);
     }
 });
 layout.addview(startanother);
 button startcontentprovider = new button(getapplication());
 startcontentprovider.settext("start a contentprovider");
 startcontentprovider.setonclicklistener(new view.onclicklistener() {
     public void onclick(view v) {
  getcontentresolver().query(contentproviderdemo.content_uri, null, null, null, null);
     }
 });
 layout.addview(startcontentprovider);
 button startreceiver = new button(getapplication());
 startreceiver.settext("start a broadcastreceiver");
 startreceiver.setonclicklistener(new view.onclicklistener() {
     public void onclick(view v) {
  intent i = new intent("android.action.start_broadcastreceiver_demo");
  sendbroadcast(i);
     }
 });
 layout.addview(startreceiver);
 setcontentview(layout);

 mmainhandler.sendemptymessagedelayed(0, 500);
    }

    public void dumpthreadinfo() {
 thread.dumpstack();
 log.e(tag, thread.currentthread().tostring());
 log.e(tag, " " + getmainlooper());
    }
}

 

复制代码 代码如下:


public class anotheractivity extends activity {
    private static final string tag = "anotheractivity";
    private handler mmainhandler = new handler(getmainlooper(), new handler.callback() {
        public boolean handlemessage(message msg) {
            // this will cause anr
            log.e(tag, "you know what this is very slow slow slow slow");
            systemclock.sleep(20 * 1000);
            dumpthreadinfo();
            return false;
        }
    });
    @override
    protected void oncreate(bundle savedinstancestate) {
 dumpthreadinfo();
 super.oncreate(savedinstancestate);

 settitle("this is another activity");
 mmainhandler.sendemptymessagedelayed(0, 500);
    }
    @override
    protected void ondestroy() {
 dumpthreadinfo();
 super.ondestroy();
    }
    public void dumpthreadinfo() {
 thread.dumpstack();
 log.e(tag, thread.currentthread().tostring());
 log.e(tag, " " + getmainlooper());
    }
}

 

复制代码 代码如下:


public class servicedemo extends service {
    private handler mmainhandler = new handler(new handler.callback() {
        public boolean handlemessage(message msg) {
            // this will cause anr, too
            log.e(tag, "this is very slow you know, slow slow");
            systemclock.sleep(20 * 1000);
            dumpthreadinfo();
            return false;
        }
    });
    private static final string tag = "servicedemo";
    @override
    public ibinder onbind(intent arg0) {
 dumpthreadinfo();
 return null;
    }
    @override
    public void oncreate() {
 dumpthreadinfo();
 super.oncreate();
 mmainhandler.sendemptymessagedelayed(0, 500);
    }
    @override
    public int onstartcommand(intent intent, int flags, int startid) {
 dumpthreadinfo();
 return super.onstartcommand(intent, flags, startid);
    }

    public void dumpthreadinfo() {
 thread.dumpstack();
 log.e(tag, thread.currentthread().tostring());
 log.e(tag, " " + getmainlooper());
    }
}

 

复制代码 代码如下:


public class contentproviderdemo extends contentprovider {
    public static final uri content_uri = uri.parse("content://com.hilton.effectiveandroid.app/content");
    private static final string tag = "contentproviderdemo";
    @override
    public int delete(uri arg0, string arg1, string[] arg2) {
 dumpthreadinfo();
 return 0;
    }
    @override
    public uri insert(uri uri, contentvalues values) {
 dumpthreadinfo();
 return null;
    }
    @override
    public boolean oncreate() {
 dumpthreadinfo();
 return false;
    }
    @override
    public cursor query(uri uri, string[] projection, string selection, string[] selectionargs, string sortorder) {
 dumpthreadinfo();
 // it will cause anr of course
 log.e(tag, "this is very slow, you know that");
 systemclock.sleep(20 * 1000);
 return null;
    }
    @override
    public int update(uri uri, contentvalues values, string selection, string[] selectionargs) {
 dumpthreadinfo();
 return 0;
    }

    public void dumpthreadinfo() {
 thread.dumpstack();
 log.e(tag, thread.currentthread().tostring());
    }
    @override
    public string gettype(uri arg0) {
 return null;
    }
}

 

复制代码 代码如下:


public class broadcastreceiverdemo extends broadcastreceiver {
    private static final string tag = "broadcastreceiverdemo";
    @override
    public void onreceive(context context, intent intent) {
 log.e(tag, "intent is " + intent);
 dumpthreadinfo();
    }

    public void dumpthreadinfo() {
 thread.dumpstack();
 log.e(tag, thread.currentthread().tostring());
    }
}

延伸 · 阅读

精彩推荐
  • Android汇总Android视频录制中常见问题

    汇总Android视频录制中常见问题

    这篇文章主要汇总了Android视频录制中常见问题,帮助大家更好地解决Android视频录制中常见的问题,需要的朋友可以参考下...

    yh_thu5192021-04-28
  • AndroidAndroid中AsyncTask详细介绍

    Android中AsyncTask详细介绍

    这篇文章主要介绍了Android中AsyncTask详细介绍,AsyncTask是一个很常用的API,尤其异步处理数据并将数据应用到视图的操作场合,需要的朋友可以参考下...

    Android开发网7432021-03-11
  • AndroidAndroid程序设计之AIDL实例详解

    Android程序设计之AIDL实例详解

    这篇文章主要介绍了Android程序设计的AIDL,以一个完整实例的形式较为详细的讲述了AIDL的原理及实现方法,需要的朋友可以参考下...

    Android开发网4622021-03-09
  • AndroidAndroid CardView+ViewPager实现ViewPager翻页动画的方法

    Android CardView+ViewPager实现ViewPager翻页动画的方法

    本篇文章主要介绍了Android CardView+ViewPager实现ViewPager翻页动画的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    Abby代黎明9592022-03-02
  • AndroidAndroid实现Service获取当前位置(GPS+基站)的方法

    Android实现Service获取当前位置(GPS+基站)的方法

    这篇文章主要介绍了Android实现Service获取当前位置(GPS+基站)的方法,较为详细的分析了Service基于GPS位置的技巧,具有一定参考借鉴价值,需要的朋友可以参考下...

    Ruthless8332021-03-31
  • AndroidAndroid界面效果UI开发资料汇总(附资料包)

    Android界面效果UI开发资料汇总(附资料包)

    android ui界面设计,友好的界面会提高用户体验度;同时也增强了android ui界面设计的难度,本文提供了一些常用开发资料(有下载哦)感兴趣的朋友可以了解下...

    Android开发网4652021-01-03
  • AndroidAndroid编程解析XML方法详解(SAX,DOM与PULL)

    Android编程解析XML方法详解(SAX,DOM与PULL)

    这篇文章主要介绍了Android编程解析XML方法,结合实例形式详细分析了Android解析XML文件的常用方法与相关实现技巧,需要的朋友可以参考下...

    liuhe68810042021-05-03
  • AndroidAndroid实现固定屏幕显示的方法

    Android实现固定屏幕显示的方法

    这篇文章主要介绍了Android实现固定屏幕显示的方法,实例分析了Android屏幕固定显示所涉及的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...

    鉴客6182021-03-27