zoukankan      html  css  js  c++  java
  • Android的进程,线程模型

    Android 包括一个应用程序框架、几个应用程序库和一个基于 Dalvik 虚拟机的运行时,所有这些都运行在 Linux 内核之上。

    通过利用 Linux 内核的优势,Android 得到了大量操作系统服务,包括进程和内存管理、网络堆栈、驱动程序、硬件抽象层、安全性等相关的服务。

    有关Java虚拟机跟进程,线程的关系请参看下面这篇文章:

    进程、线程与JVM、CLR
    http://blog.csdn.net/ghj1976/archive/2010/04/13/5481038.aspx

    下面这篇文章对Android的进程和线程描述的很好,我在这篇文章基础补充了一些图片和信息。

    http://blog.csdn.net/L_serein/archive/2011/03/22/6269270.aspx 

    android进程模型:

    在安装Android应用程序的时候,Android会为每个程序分配一个Linux用户ID,并设置相应的权限,这样其它应用程序就不能访问此应用程序所拥有的数据和资源了。

    在 Linux 中,一个用户ID 识别一个给定用户;在 Android 上,一个用户ID 识别一个应用程序。

    应用程序在安装时被分配用户 ID,应用程序在设备上的存续期间内,用户ID 保持不变。

    默认情况下,每个apk运行在它自己的Linux进程中。当需要执行应用程序中的代码时,Android会启动一个jvm,即一个新的进程来执行,因此不同的apk运行在相互隔离的环境中。

    下图显示了:两个 Android 应用程序,各自在其自己的基本沙箱或进程上。他们是不同的Linux user ID。

    image

    开发者也可以给两个应用程序分配相同的linux用户id,这样他们就能访问对方所拥有的资源。

    为了保留系统资源,拥有相同用户id的应用程序可以运行在同一个进程中,共享同一个jvm。

    如下图,显示了两个 Android 应用程序,运行在同一进程上。

    不 同的应用程序可以运行在相同的进程中。要实现这个功能,首先必须使用相同的私钥签署这些应用程序,然后必须使用 manifest 文件给它们分配相同的 Linux 用户 ID,这通过用相同的值/名定义 manifest 属性 android:sharedUserId 来做到。

    image

    Android进程知识的补充:

    下图是标准的Android 架构图,

    其中我们可以看到在“Android本地库 & Java运行环境层”中,Android 运行时中,

    Dalvik是Android中的java虚拟机,可支持同时运行多个虚拟机实例;每个Android应用程序都在自己的进程中运行,都拥有一个独立的Dalvik虚拟机实例;
    所有java类经过java编译器编译,然后通过SDK中的dx工具转成.dex格式交由虚拟机执行。

    image

    Android系统进程

    init进程(1号进程),父进程为0号进程,执行根目录底下的init可执行程序,是用户空间进程
    ——-> /system/bin/sh
    ——-> /system/bin/mediaserver
    ——-> zygote
    —————–> system_server
    —————–>com.android.phone
    —————–>android.process.acore(Home)
    … …

    kthreadd进程(2号进程),父进程为0号进程,是内核进程,其他内核进程都是直接或者间接以它为父进程

      

    Android的单线程模型

    当一个程序第一次启动时,Android会同时启动一个对应的主线程(Main Thread),主线程主要负责处理与UI相关的事件,如:用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理。所以主线程通常又被叫做UI线程。

    在开发Android 应用时必须遵守单线程模型的原则: Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。

    如 果在非UI线程中直接操作UI线程,会抛出 android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views,这与普通的java程序不同。

    由于UI线程负责事件的监听和绘图,因此,必须保证UI线程能够随时响应用户的需求,UI线程里的操作应该向中断事件那样短小,费时的操作(如网络连接)需要另开线程,否则,如果UI线程超过5s没有响应用户请求,会弹出对话框提醒用户终止应用程序。

    如果在新开的线程中需要对UI进行设定,就可能违反单线程模型,因此android采用一种复杂的Message Queue机制保证线程间通信。

    Message Queue:

    Message Queue是一个消息队列,用来存放通过Handler发布的消息。Android在第一次启动程序时会默认会为UI thread创建一个关联的消息队列,可以通过Looper.myQueue()得到当前线程的消息队列,用来管理程序的一些上层组 件,activities,broadcast receivers 等等。你可以在自己的子线程中创建Handler与UI thread通讯。 

    通过Handler你可以发布或者处理一个消息或者是一个Runnable的实例。每个Handler都会与唯一的一个线程以及该线程的消息队列管理。

    Looper 扮演着一个Handler和消息队列之间通讯桥梁的角色。程序组件首先通过Handler把消息传递给Looper,Looper把消息放入队列。 Looper也把消息队列里的消息广播给所有的Handler,Handler接受到消息后调用handleMessage进行处理。

    实例如下:

    public void onCreate(Bundle savedInstanceState) {  
       super.onCreate(savedInstanceState);  
       setContentView(R.layout.main);  
       editText = (EditText) findViewById(R.id.weather_city_edit);  
       Button button = (Button) findViewById(R.id.goQuery);  
       button.setOnClickListener(this);  
    
       Looper looper = Looper.myLooper();  //得到当前线程的Looper实例,由于当前线程是UI线程也可以通过Looper.getMainLooper()得到  
        messageHandler = new MessageHandler(looper);  //此处甚至可以不需要设置Looper,因为 Handler默认就使用当前线程的Looper  
    } 
    
    public void onClick(View v) {  
       new Thread() {  
          public void run() {  
              Message message = Message.obtain();  
              message.obj = "abc";  
              messageHandler.sendMessage(message);  //发送消息 
           }  
       }.start();  
    } 
    
    Handler messageHandler = new Handler {  
       public MessageHandler(Looper looper) {  
          super(looper);  
      } 
       public void handleMessage(Message msg) {  
          setTitle((String) msg.obj);  
       } 
    }

    对于这个实例,当这个activity执行玩oncreate,onstart,onresume后,就监听UI的各种事件和消息。

    当我们点击一个按钮后,启动一个线程,线程执行结束后,通过handler发送一个消息,由于这个handler属于UI线程,因此这个消息也发送 给UI线程,然后UI线程又把这个消息给handler处理,而这个handler是UI线程创造的,他可以访问UI组件,因此,就更新了页面。

    由于通过handler需要自己管理线程类,如果业务稍微复杂,代码看起来就比较混乱,因此android提供了AsyncTask类来解决此问题。

    AsyncTask:

    首先继承一下此类,实现以下若干方法,

    onPreExecute(), 该方法将在执行实际的后台操作前被UI thread调用。可以在该方法中做一些准备工作,如在界面上显示一个进度条。 

    doInBackground(Params...), 将在onPreExecute 方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台计算工作。

    可以调用publishProgress方法来更新实时的任务进度。该方法是抽象方法,子类必须实现。 

    onProgressUpdate(Progress...),在publishProgress方法被调用后,UI thread将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。 

    onPostExecute(Result), 在doInBackground 执行完成后,onPostExecute 方法将被UI thread调用,后台的计算结果将通过该方法传递到UI thread.

    使用时需要遵循以下规则:

    1)Task的实例必须在UI thread中创建 

    2)execute方法必须在UI thread中调用 

    3)不要手动的调用这些方法,只调用execute即可

    4)该task只能被执行一次,否则多次调用时将会出现异常

    示例如下:

    public void onCreate(Bundle savedInstanceState) {  
           super.onCreate(savedInstanceState);  
           setContentView(R.layout.main);  
           editText = (EditText) findViewById(R.id.weather_city_edit);  
           Button button = (Button) findViewById(R.id.goQuery);  
           button.setOnClickListener(this);  
    }  
    
    public void onClick(View v) {  
           new GetWeatherTask().execute(“aaa”);  
    } 
    
    class GetWeatherTask extends AsyncTask<String, Integer, String> {  
        protected String doInBackground(String... params) {  
             return getWetherByCity(params[0]);  
        } 
        protected void onPostExecute(String result) {  
             setTitle(result);
        }  
    }

    参考资料:
    Android进程和线程模型
    http://blog.csdn.net/L_serein/archive/2011/03/22/6269270.aspx

    Hello Android 第三版 (二)
    http://blog.csdn.net/cqwty/archive/2010/09/08/5870219.aspx

    理解 Android 上的安全性
    http://www.ibm.com/developerworks/cn/xml/x-androidsecurity/

    sourceurl:http://www.cnblogs.com/ghj1976/archive/2011/04/28/2031586.html

  • 相关阅读:
    【BZOJ 4581】【Usaco2016 Open】Field Reduction
    【BZOJ 4582】【Usaco2016 Open】Diamond Collector
    【BZOJ 4580】【Usaco2016 Open】248
    【BZOJ 3754】Tree之最小方差树
    【51Nod 1501】【算法马拉松 19D】石头剪刀布威力加强版
    【51Nod 1622】【算法马拉松 19C】集合对
    【51Nod 1616】【算法马拉松 19B】最小集合
    【51Nod 1674】【算法马拉松 19A】区间的价值 V2
    【BZOJ 2541】【Vijos 1366】【CTSC 2000】冰原探险
    【BZOJ 1065】【Vijos 1826】【NOI 2008】奥运物流
  • 原文地址:https://www.cnblogs.com/hnrainll/p/2314534.html
Copyright © 2011-2022 走看看