Android多线程/进程通信(Socket/IPC/Binder/AIDL/Messenger Demo),多进程的坑

-- 进程与线程:
 进程是对运行时程序的封装,可以保存程序的运行状态,实现操作系统的并发;
 线程是进程的子任务,保证程序的实时性;
 进程是操作系统资源的分配单位,线程是CPU调度的基本单位;
 进程让操作系统的并发性成为可能,而线程让进程的内部并发成为可能。

线程从创建、运行到结束总是处于下面五个状态之一:新建状态、就绪状态、运行状态、阻塞状态及死亡状态。
Android多线程的多种方式: 1.Handler+Thread; 2.AsyncTask; 3.ThreadPoolExecutor; 4.IntentService 5.HandlerThread
Android中进程类型:1 前台进程;2 可视进程;3 服务进程;4 后台进程;5 空进程

-- Messenger : Messenger 即信使的意思, 看起来它就与 Message 对象有关,因为这个对象就是用来在不同进程中传递 Message 对象的。Messenger 是一种轻量级的 IPC 方案,它的底层实现是 AIDL。
  使用 Messenger 进行客户端与服务端之间的双向通信还是蛮容易的,相比 AIDL, 这个方案相当的便捷。因为使用的是串行方式处理信息,所以 Messenger 比较适用于并发的一对多的通信。不同的场景下还是需要找到最合适的方案。还是那句话,每个方案都是针对不同的业务场景而设计的,总之,找到合适的就是最好的。
  服务端在收到消息后会使用 Message.replyTo 对应的信使回复消息。message.replyTo = mClientMessenger;
  服务端与客户端通信,主要是在传输的消息上做了处理,让Messager.replyTo指向的客户端的Messenger,而Messenger又持有客户端的一个Binder对象(MessengerImpl)。服务端正是利用这个Binder对象做的与客户端的通信。 其实messenger底层也是AIDL。客户端和服务端通讯,就是普通的AIDL,客户端实例化stub之后,通过stub的send方法把消息发到服务端。服务端和客户端通讯:服务端通过解析message的replyto,获得客户端的stub,然后通过send方法发送到客户端。

- Android 中的 IPC 机制有哪些:
1.组件间使用 Intent 传递数据;
2.文件共享;
3.Messenger;
4.AIDL;
5.ContentProvider;
6.Socket;

-- Android IPC点将台- https://juejin.im/post/5cd2971f51882541c90ee112
IPC的几种形式:
[1].通过Intent传递Bundle对象通信: 简单,数据类型局限,用于组件间传递数据
[2].使用共享文件通信: 简单,实时性差,不适合高并发
[3].使用Messenger通信: 支持一对多串行通信,支持实时通信,不支持RPC
[4].使用AIDL通信: 支持一对多并发通信,适用于,一对多通信且有RPC需求
[5].使用ContentProvider: 支持一对多并发数据共享
[6].使用Socket: 可以通过网络传输字节流,支持一对多并发实时通信
> 多线程/多进程 demo
使用Socket处理跨进程的实时聊天- https://github.com/SpikeKing/SocketDemo
实现AIDL接口的Binder连接池- https://github.com/SpikeKing/BinderPoolDemo
使用 ContentProvider 跨进程共享数据- https://github.com/SpikeKing/ContentProviderDemo
使用AIDL实现Android的跨进程通信- https://github.com/SpikeKing/wcl-aidl-demo
Android 进程使用 Messenger 通信- https://github.com/SpikeKing/wcl-messenger-demo
Android Binder IPC framework进程间通讯binder机制client,server实现代码-https://github.com/twitter-university/FibonacciBinderDemo

-- Android 跨进程双向通信(Messenger与AIDL)
Messenger和AIDL的主要区别- https://github.com/libin7278/IPC

> Android多线程, Android 主线程与子线程通信

线程通信:1.子线程向主线程传值;2.主线程向子线程里发送消息;3.子线程和子线程之间通信。

多线程编程中最最基础的条件要保证数据的完整性。多线程之间交换数据靠内存来完成。

Android线程管理(一)——线程通信- http://www.cnblogs.com/younghao/p/5116819.html
Android线程管理(二)——ActivityThread- http://www.cnblogs.com/younghao/p/5126408.html
Android线程管理(三)——Thread类的内部原理、休眠及唤醒-http://www.cnblogs.com/younghao/p/5141295.html
40个Java多线程问题总结- http://geek.csdn.net/news/detail/197712?ref=myread

-- 线程的生命周期分为:创建(new)、就绪(Runnable)、运行(running)、阻塞(Blocked)、死亡(Dead)五种状态。
线程状态的控制:start(),interrupt(),join(),setDaemon(boolean on),setPriority(int newPriority),sleep(long millis),stop(),yield()。

-- 多线程的应用在Android开发中是非常常见的,常用方法主要有:
1.继承Thread类;2.实现Runnable接口;3.Handler;4.AsyncTask;5.HandlerThread;6.IntentService;

-- 为Android主线程减轻负的多线程方案有哪些呢?这些方案分别适合在什么场景下使用:
 1.AsyncTask: 为 UI 线程与工作线程之间进行快速的切换提供一种简单便捷的机制。适用于当下立即需要启动,但是异步执行的生命周期短暂的使用场景。封装了线程池和Handler,主要是为了方便开发者在子线程中更新UI。
 2.HandlerThread: 为某些回调方法或者等待某些任务的执行设置一个专属的线程,并提供线程任务的调度机制。具有消息循环的线程,在它的内部可以使用Handler。
 3.ThreadPool: 把任务分解成不同的单元,分发到各个不同的线程上,进行同时并发处理。
 4.IntentService: 适合于执行由 UI 触发的后台 Service 任务,并可以把后台任务执行的情况通过一定的机制反馈给 UI。内部采用HandlerThread来执行任务,当任务执行完毕后IntentService会自动退出。

-- Handler,子线程向主线程传值:
private Handler mHandler;
    private final static int imageview_update_msg = 100;
    private void initData() {
        mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what) {
                    case imageview_update_msg:
                        effectIv.setImageBitmap((Bitmap) msg.obj);
                        break;
                    default:
                        break;
                }
            }
        };
    }
Runnable subRun = new Runnable() {//创建匿名内部类
        @Override
        public void run() {
//            effectIv.setImageBitmap(PictureUtils.oldRemeber(context));
            Bitmap bitmap = PictureUtils.oldRemeber(context);
            Log.e("desaco", "VideoSubFragment1,excute Runnable,bitmap=" + bitmap);


            //子线程向主线程发送消息
            Message message = Message.obtain();
            message.what = imageview_update_msg;
            message.obj = bitmap;
            mHandler.sendMessage(message);
        }
    };

-- Handler与handlerThread
Android使用Handler实现子线程与子线程、主线程之间通信- https://blog.csdn.net/shaoenxiao/article/details/54561753?utm_source=itdadao&utm_medium=referral

Android HandlerThread 总结使用- https://www.cnblogs.com/zhaoyanjun/p/6062880.html
HandlerThread的特点:主线程发消息给子线程,告诉子线程需要处理一个耗时的操作,即主线程向子线程里发送消息
 1.HandlerThread将loop转到子线程中处理,说白了就是将分担MainLooper的工作量,降低了主线程的压力,使主界面更流畅。
 2.开启一个线程起到多个线程的作用。处理任务是串行执行,按消息发送顺序进行处理。HandlerThread本质是一个线程,在线程内部,代码是串行处理的。
 3.但是由于每一个任务都将以队列的方式逐个被执行到,一旦队列中有某个任务执行时间过长,那么就会导致后续的任务都会被延迟处理。
 4.HandlerThread拥有自己的消息队列,它不会干扰或阻塞UI线程。
 5.对于网络IO操作,HandlerThread并不适合,因为它只有一个线程,还得排队一个一个等着。

-- HandlerThread:
1.HandlerThread本质上是一个Thread对象,只不过其内部帮我们创建了该线程的Looper和MessageQueue;
2.通过HandlerThread我们不但可以实现UI线程与子线程的通信同样也可以实现子线程与子线程之间的通信;
3.HandlerThread在不需要使用的时候需要手动的回收掉;

HandlerThread是一个集成了Looper和MessageQueue的线程,当启动HandlerThread时,会同时生成Looper和MessageQueue,然后等待消息进行处理.

-- Android中Activity、Service、Fragment之间的相互通信比较麻烦,主要有以下几种方式:
(1)使用广播,发送者发出广播,接收者接收广播后进行处理;
(2)使用Handler和Message,如下载线程完成下载任务后,给UI发送Message,UI收到Message后更新界面。
(3)简单有效的方法事件总线。

  在早期的系统中,多线程或多进程是最常用的技术。这种技术的代码编写起来比较简单,因为每个线程中的代码都肯定是按先后顺序执行的。但是由于同时运行着多个线程,所以你无法保障多个线程之间的代码的先后顺序。这对于需要处理同一个数据的逻辑来说,是一个非常严重的问题,最简单的例子就是显示某个新闻的阅读量。两个++操作同时运行,有可能结果只加了1,而不是2。所以多线程下,我们常常要加很多数据的锁,而这些锁又反过来可能导致线程的死锁。
  因此异步回调模型在随后比多线程更加流行,除了多线程的死锁问题外,异步还能解决多线程下,线程反复切换导致不必要的开销的问题:每个线程都需要一个独立的栈空间,在多线程并行运行的时候,这些栈的数据可能需要来回的拷贝,这额外消耗了CPU。同时由于每个线程都需要占用栈空间,所以在大量线程存在的时候,内存的消耗也是巨大的。而异步回调模型则能很好的解决这些问题,不过异步回调更像是“手工版”的并行处理,需要开发者自己去实现如何“并行”的问题。
  异步回调基于非阻塞的I/O操作(网络和文件),这样我们就不用在调用读写函数的时候“卡”在那一句函数调用,而是立刻返回“有无数据”的结果。而Linux的epoll技术,则利用底层内核的机制,让我们可以快速的“查找”到有数据可以读写的连接\文件。由于每个操作都是非阻塞的,所以我们的程序可以只用一个进程,就处理大量并发的请求。因为只有一个进程,所以所有的数据处理,其顺序都是固定的,不可能出现多线程中,两个函数的语句交错执行的情况,因此也不需要各种“锁”。从这个角度看,异步非阻塞的技术,是大大简化了开发的过程。由于只有一个线程,也不需要有线程切换之类的开销,所以异步非阻塞成为很多对吞吐量、并发有较高要求的系统首选。

  很多利用请求方内存的缓冲算法和技术,其中最简单的就是使用LRU算法,把数据放在一个哈希表结构的堆内存中。

-- 用于实现后台线程与UI线程的交互 -- http://blog.csdn.net/anroidfinalbreak/article/details/38338107
  一般通过Thread与hander来协调完成。
【Android 并发编程】线程间通信的三种基本方式:使用管道流Pipes;共享内存;使用Hander和Message
 Looper对象:Looper.myLooper() == Looper.getMainLooper()
 mChildHandler.getLooper().quit();
 Looper.prepare(); Looper.loop();

-- 使用wait/notify/notifyAll实现线程间通信
 UI线程与子线程交互五种方式:
1、handler
2、Activity.runOnUIThread(Runnable)
3、View.Post(Runnable)
4、View.PostDelayed(Runnabe,long)
5、AsyncTask

1.runOnUiThread(Runnable)              在子线程中直接使用该方法,可以更新UI
runOnUiThread(new Runnable(){//更新UI
       @Override
        public void run() {
              publish_time.setText("更新失败");
         } 
   });
2.View.postDelay(Runnable , long)/new Handler().postDelayed(Runnable)
 在需要更新UI的地方调用该方法,Runnable对象的方法里,直接操作UI;long是指延迟多少秒
//延迟一秒钟出现
        new Handler().postDelayed(new Runnable() {          
            @Override
            public void run() {
                // TODO Auto-generated method stub
                notify_view_text.setText(String.format(getString(R.string.ss_pattern_update), 10));
                notify_view.setVisibility(View.VISIBLE);
                //延迟两秒钟消失
                new Handler().postDelayed(new Runnable() {
                    
                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        notify_view.setVisibility(View.GONE);
                    }
                }, 2000);
            }
        }, 1000);
3.使用Handler
4.使用AsyncTask

-- 主线程的话 可以直接调用子线程, 获取线程Id和进程Id
import android.os.Process;
Process.myTid()  ----------get current thread id
Process.myPid()  ----------get current Process id

主线程与子线程的Id:
LogManagerControl.ShowLog(TAG, "Thread(),thread id="+android.os.Process.myTid(), "V");
LogManagerControl.ShowLog(TAG, "onResume(),thread id="+android.os.Process.myTid(), "V");
LogManagerControl.ShowLog(TAG, "Handler(),thread id="+android.os.Process.myTid(), "V");
主线程的Id和Handler的Id是一样的,子线程的Id不一样的

-- AsyncTask的同步异步问题???AsyncTask内部有一个线程池?
  AsyncTask有如下问题:
1.默认的AsyncTask如果处理的任务过多,会导致程序直接崩溃;
2.AsyncTask类必须在主线程初始化,必须在主线程创建,不然在API 16以下很大概率崩溃。
3.如果你曾经使用过AsyncTask,以后不用了;在Android 4.4以下,进程内也默认有5个AsyncTask线程;在Android 4.4以上,默认有CPU + 1个线程。
4.Android 3.0以上的AsyncTask默认是串行执行任务的;如果要并行执行需要调用低版本没有的API,处理麻烦。

  AsyncTask这个类的实现可谓一波三折,方案修改了好几个版本,初次引入这个类时,所有的Task是放在一个独立的后台线程中执行的,也就是如果有多个Task同时被调用也是顺序执行的;从1.6开始,改为通过线程池可以支持并行执行多个Task;但从3.0开始,又改回只有一个独立的后台线程执行所有Task,主要是为了避免多个Task并行执行导致的程序错误,但为了让AsyncTask能够支持多个Task并行执行,从3.0起,增加了executeOnExecutor方法,调用者自行实现线程池可以达到并行多个Task的效果。

Android多线程(二)AsyncTask源码分析-- http://blog.csdn.net/itachi85/article/details/45041923
Android并发编程之全方位解析AsyncTask-- http://blog.csdn.net/nugongahou110/article/details/49992693
 AsyncTask被设计为同一个对象只能执行一次.
 AsyncTask串行:new MyAsyncTask(this,0).execute();
 AsyncTask并行:new MyAsyncTask(this,0).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
 AsyncTask内部实现其实就是Thread+Handler。其中Handler是为了处理线程之间的通信,而这个Thread到底是指什么呢?通过AsyncTask源码可以得知,其实这个Thread是线程池,AsyncTask内部实现了两个线程池,分别是:串行线程池和固定线程数量的线程池。而这个固定线程数量则是通过CPU的数量决定的。
  在AsyncTask和IntentService的内部亦使用了Handler实现其主要功能。
  如hibernate,EventBus,Handler都运用了ThreadLocal进行线程相关的操作。ThreadLocal并不是用来操作什么本地线程而是用于实现不同线程的数据副本。当使用ThreadLocal维护变量时,它会为每个使用该变量的线程提供独立的变量副本;每一个线程都可以独立地改变自己的副本并且不会影响其它线程所持有的对应的副本。所以,ThreadLocal的实际作用并不与它的名字所暗含的意义相吻合,或许改称为ThreadLocalVariable(线程本地变量)会更合适一些。
  Executor Framework, 创建和销毁对象是存在开销的,在应用中频繁出现线程的创建和销毁,那么会影响到应用的性能,使用Executor框架可以通过线程池机制解决这个问题,改善应用的体验。
   AsyncTask是在Executor框架基础上进行的封装,它实现将耗时任务移动到工作线程中执行,同时提供方便的接口实现工作线程和主线程的通信.在executeOnExecutor(AsyncTask.SERIAL_EXECUTOR)或者API大于13的系统上面执行execute()方法.

Android多线程一(AsyncTask实现原理)-http://blog.csdn.net/pipisky2006/article/details/8270222
AsyncTask的本质是一个线程池 BlockingQueue<Runnable> LinkedBlockingQueue<Runnable>(10) 
总结:
1、 AsyncTask的本质是一个静态的线程池,AsyncTask派生出的子类可以实现不同的异步任务,这些任务都是提交到静态的线程池中执行。
2、线程池中的工作线程执行doInBackground(mParams)方法执行异步任务
3、当任务状态改变之后,工作线程会向UI线程发送消息,AsyncTask内部的InternalHandler响应这些消息,并调用相关的回调函数
4,AsyncTask在Activity因为OnConfiguration重绘时要注意。
  Android 原生的 AsyncTask.java 是对线程池的一个封装,使用其自定义的 Executor 来调度线程的执行方式(并发还是串行),并使用 Handler 来完成子线
程和主线程数据的共享。
  尽管Java中的多线程是个很好的机制,但是在使用时要注意它的副作用,学会使用对他进行封装之后的类和方法。

-- 主线程向子线程发消息,子线程向主线程发消息  Android (ThreadLocal/HandlerThread)

棒棒糖之主线程和子线程的异步技术链详细讲解- https://my.oschina.net/u/2011321/blog/891044
 本质上来说,Handler并不是专门用于更新UI的,它只是常被大家用来更新UI。 Android的消息机制主要是指Handler的运行机制,Handler的运行需要底层的MessageQueue和Looper的支撑。ThreadLocal是一个线程内部的数据存储类;ThreadLocal另一个使用场景是复杂逻辑下的对象传递,比如监听器的传递.
Android子线程中更新UI的3种方法- http://blog.csdn.net/u011682673/article/details/53207700
Android HandlerThread 完全解析- http://blog.csdn.net/lmj623565791/article/details/47079737/
Looper.prepare(),Looper.loop(),Handler.getLooper().quit()
Android主线程向子线程中发送信息- http://blog.csdn.net/shyboyes/article/details/50087875
Android Looper.prepare()和Looper.loop() - http://blog.csdn.net/heng615975867/article/details/9194219

如果线程中使用Looper.prepare()和Looper.loop()创建了消息队列,就可以让消息处理在该线程中完成,Looper用于封装了android线程中的消息循环
class LooperThread extends Thread {  
  public Handler mHandler;  
  public void run(){  
     Looper.prepare();  
     mHandler = new Handler(){  
        public void handleMessage(Message msg){  
           // process incoming messages here  
}  
     };  
    Looper.loop();  
  }
}  
注:写在Looper.loop()之后的代码不会被马上执行。当调用后mHandler.getLooper().quit()后。loop才会中止,其后的代码才得以执行。

-- 线程的优先级
  为了提高 我们的Activity中的线程的线程优先级(Thread-Priority),我们需要在AndroidManifest.xml 中使用 'uses-permission' 这样做:  XML:  <uses-permission id="android.permission.RAISED_THREAD_PRIORITY"/>
 现在你可以在你的Activity中使用以下代码改变或提高任何线程的优先级:
Java:  import android.os.Process;
// -----------------------------------
// Set the priority of the calling thread, based on Linux priorities:
// -----------------------------------
// Changes the Priority of the calling Thread!
Process.setThreadPriority(12);
// Changes the Priority of passed Thread (first param)
Process.setThreadPriority(Process.myTid(), 12);

这里 range 的范围是 -20 (高) 到 +19 (低). 不要选得 太高,最好使用预先定义在 android.os.Process 的constants :
// Lower is 'more impotant'
Process.THREAD_PRIORITY_LOWEST = 19
Process.THREAD_PRIORITY_BACKGROUND = 5
Process.THREAD_PRIORITY_DEFAULT = 0
Process.THREAD_PRIORITY_FOREGROUND = -5
Process.THREAD_PRIORITY_DISPLAY = -10
Process.THREAD_PRIORITY_URGENT_DISPLAY = -15

> Android多进程, 进程间通信

  Android会为每个程序分配一个Linux用户ID,并设置相应的权限,沙箱;android采用一种复杂的Message Queue机制保证线程间通信.

进程间通信:Bundle/Intent传递数据,Messenger,AIDL,ContentProvider,Socket,广播。
Android跨进程通信(几种进程通讯):Intent,aidl,messager,content provider,广播。
Android 进程使用 Messenger 通信,使用AIDL实现Android的跨进程通信,使用ContentProvider跨进程共享数据。
APK进程是如何怀胎十月之后诞生的?

  进程就相当于工厂,线程就是工厂里的流水线,线程不能独立存在,必须存在于进程中。
  多进程:系统中同时存在多个并行的进程,则称为多进程。可通过电脑任务管理器查看正在运行的进程,比如用电脑聊QQ的同时看电影,就是多进程的体现。 
  多线程:线程是进程中的单个顺序控制流,是一条执行路径,一个进程如果有多条执行路径,则称为多线程。比如给某人聊QQ的同时还可以接收到其他人的消息。
Android 应用内多进程实现:http://www.cnblogs.com/shaweng/p/4016296.html
进程间线程间的同步锁原理和种类-- http://blog.csdn.net/blues1021/article/details/44318321
多线程和多进程中避免锁机制注意的几点-- http://www.cnblogs.com/jiangwang2013/p/3398272.html
[纯干货]安卓跨进程点击事件的解决方案-http://mt.sohu.com/20160616/n454754223.shtml

-- Android进程间通信 Socket/LocalSocket
Android Socket进程通信——Client与Server之间的通信机制- http://blog.csdn.net/zibuyuyeye/article/details/49024503
Android进程间通信之Socket- http://blog.csdn.net/zhangyongfeiyong/article/details/51700650
毕设小结(二)Android进程间通信之LocalSocket- http://blog.csdn.net/xbalien29/article/details/8765235
Android进程间通信之socket通信- https://www.cnblogs.com/Joanna-Yan/p/4708293.html
跨进程、进程间通信--http://www.zhihu.com/question/24766848/answer/53037579?utm_source=weibo&utm_medium=weibo_share&utm_content=share_answer&utm_campaign=share_button

  跨进程binder,另外os级别的socket也是很好选择 Intent(Bundle)。进程间通讯(IPC)方式:
1)管道(Pipe),管道是单向的,先进先出,务结构的固定大小的字节流,常用于父子进程的通讯,Socket、流等都是管道的实现方式
2)信号,用户进程间通讯和同步的原始机制
3)消息队列,是一个存储消息的链表,允许多个进程向它写/读消息。
4)共享存储,通常由一个进程维护,其余进程对该内存区域进行读写
5) 报文(Message),套接字(Socket),
PS:其中的消息队列(Message Queue)和共享内存是Linux的System V IPC 机制中的两种。

-- 跨进程
使用Socket处理跨进程的实时聊天 - http://blog.csdn.net/u012515223/article/category/5990893
   由于应用程序之间不能共享内存。在不同应用程序之间交互数据(跨进程通讯),在android SDK中提供了4种用于跨进程通讯的方式。这4种方式正好对应于android系统中4种应用程序组件:Activity、Content Provider、Broadcast和Service。其中Activity可以跨进程调用其他应用程序的Activity;Content Provider可以跨进程访问其他应用程序中的数据(以Cursor对象形式返回),当然,也可以对其他应用程序的数据进行增、删、改操 作;Broadcast可以向android系统中所有应用程序发送广播,而需要跨进程通讯的应用程序可以监听这些广播;Service和Content Provider类似,也可以访问其他应用程序中的数据,但不同的是,Content Provider返回的是Cursor对象,而Service返回的是Java对象,这种可以跨进程通讯的服务叫AIDL服务。
  AIDL IPC机制是面向接口的,像COM或Corba一样,但是更加轻量级。它是使用代理类在客户端和实现端传递数据。说明:通过AIDL传输非基本类型的对象,被传输的对象需要序列化,序列化功能java有提供,但是android sdk提供了更轻量级更方便的方法,即实现Parcelable接口
  Android中的RPC机制是为了实现一个进程使用另一个进程中的远程对象,它使用了Android自己的AIDL(接口定义语言),使用户很方便地定义出一个接口作为规范,通过一个远程Service为代理 ,客户端在绑定该远程Service过程中获取远程对象,进而使用该对象。
 
 //启动服务  
Intent intentService = new Intent(MyActivity.this, MyService.class);  
intentService.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
intentService.setAction("scott");  
//bindService用于和service进行交互  
MyActivity.this.bindService(intentService, mServiceConnection, BIND_AUTO_CREATE);  
//startService用于启动service但是不和其交互  
startService(intentService);  

  在Linux中,文件描述符都是属于进程的,用整数来表示。通过fork,虽然子进程和父进程都是打开同样的文件,但文件描述符却是不同的。 同样的文件描述符值在不同进程对应不同的文件描述符值数组。 所以文件描述符透过Binder来进行传输时,不能是简单的拷贝文件描述符值。 

-- IPC基础概念Serializable、Parcelable、Binder- http://blog.csdn.net/zhangyongfeiyong/article/details/51694063

   在Android中序列化对象主要有两种方式,实现Serializable接口或是实现Parcelable接口。Serializable接口是JavaSE原生支持的,而Parcelable接口是Android所特有的,它的序列化和反序列化的效率均比Serializable接口高

1.Serializable是Java提供的接口,使用简单但是开销很大,序列化和反序列化过程需要大量的I/O操作
2.而Parcelable是Android中的序列化方式,使用稍微麻烦但是效率很高。
3.直观来说,Binder是Android中的一个类,它实现了IBinder接口。
 a.从IPC角度来说,Binder是Android中的一种跨进程通信方式,Binder还可以理解为一种虚拟的物理设备,它的设备驱动是/dev/binder。
 b.从framework角度来说,Binder是ServiceManager连接各种Manager和相应ManagerService的桥梁。
 c.从Android应用层来说,Binder是客户端和服务端进行通信的媒介

Android IPC机制(一)开启多进程-- http://blog.csdn.net/itachi85/article/details/50386748
Android IPC机制(二)用Messenger进行进程间通信-- http://blog.csdn.net/itachi85/article/details/50448409
Android IPC机制(三)在Android Studio中使用AIDL实现跨进程方法调用 - -http://blog.csdn.net/itachi85/article/details/50451908
Android IPC机制(四)用ContentProvider进行进程间通信 -- http://blog.csdn.net/itachi85/article/details/50573929
Android IPC机制(五)用Socket实现跨进程聊天程序-- http://blog.csdn.net/itachi85/article/details/50667740
Android 中的IPC机制- http://blog.csdn.net/a565102223/article/details/70186070#comments
Android开发艺术探索读书笔记-进程间通信- http://blog.csdn.net/smileiam/article/details/70194042#comments?ref=myread

-- AIDL

  AIDL:Android客户端与服务使用进程间通信 (IPC) 进行相互通信时都认可的编程接口。在 Android 上,一个进程通常无法访问另一个进程的内存。 尽管如此,进程需要将其对象分解成操作系统能够识别的原语,并将对象编组成跨越边界的对象。parcelable 是谷歌提供序列化,在内存传输上效率高。
  AIDL 支持的数据类型,共 4 种:
1.Java 的基本数据类型
2.List 和 Map :元素必须是 AIDL 支持的数据类型;Server 端具体的类里则必须是 ArrayList 或者 HashMap
3.其他 AIDL 生成的接口
4.实现 Parcelable 的实体

https://img-blog.csdn.net/20180831192635639?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1NoYXJlVXM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70

-- Binder

  Binder 驱动是整个 Binder 机制的核心。除了实现数据传输之外,Binder 驱动还是实现线程控制(通过中断等待队列实现线程的等待/唤醒),以及 UID/PID 等
安全机制的保证。 
 1.Client、Server 和 ServiceManager 处于用户空间的不同进程。 
 2.Binder 实体和 Binder 引用都是内核(即 Binder 驱动)中的数据结构
Android 进阶8:进程通信之 Binder 机制浅析- http://blog.csdn.net/u011240877/article/details/72801425
 IBinder 是一个接口,它代表了一种跨进程传输的能力。只要实现了这个接口,就能将这个对象进行跨进程传递。Transtion() ,onTranstion().在 Binder 机制中,由 Binder 驱动负责完成这个中转操作,主要过程如下:
 1.当 Client 向 Server 发起 IPC 请求时,Client 会先将请求数据从用户空间拷贝到内核空间
 2.数据被拷贝到内核空间之后,驱动程序将内核空间中的数据拷贝到 Server 位于用户空间的缓存中

-- APP多进程可能会导致的问题
  1.Android Application的多次重建。Android的Application中onCreate执行多次解决方案. 每新建一个进程,Application的onCreate都将被调用一次。 这颠
覆了很多人对Application的onCreate的理解。一般人都认为只会走一次。所以在Application的onCreate中有初始化工作且需要根据进程来区分的。
 解决方法: 在Application的onCreate中获取进程名称并进行相应的判断,例如:
private static String getProcessName(Context context) {
    try {
        int pid = android.os.Process.myPid();
        ActivityManager mActivityManager = (ActivityManager) context
                .getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningAppProcessInfo appProcess : mActivityManager
                .getRunningAppProcesses()) {
            if (appProcess.pid == pid) {
                return appProcess.processName;
            }
        }
    } catch (Throwable e) {
    }
    return "";
}
private void exeOnCreate(){
    String processName = getProcessName(this, android.os.Process.myPid());
    if (!TextUtils.isEmpty(processName) && processName.equals(this.getPackageName())) {//判断进程名,保证只有主进程运行
         //主进程逻辑
    } else {
         //具体根据需要来处理。
     return;
    }
}

 2.按照正常的逻辑,静态变量是可以在应用的所有地方共享的,但是设置了process属性后,产生了两个隔离的内存空间,一个内存空间里值的修改并不会影响到另外一个内存空间。
 3.文件共享问题。多进程情况下会出现两个进程在同一时刻访问同一个数据库文件的情况。这就可能造成资源的竞争访问,导致诸如数据库损坏、数据丢失等。在多线程的情况下我们有锁机制控制资源的共享,但是在多进程中比较难,虽然有文件锁、排队等机制,但是在Android里很难实现。解决办法就是多进程的时候不并发访问同一个文件,比如子进程涉及到操作数据库,就可以考虑调用主进程进行数据库的操作。
  4.静态成员和单例失效,数据同步失败; Android会为每一个应用/每一个进程分配一个独立的虚拟机,不同虚拟机在内存分配上有不同的地址空间,这就导致不同虚拟机中访问同一个类对象会产生多个副本。 
  5.线程同步机制失效; 因为不同进程不是同一块内存,不同进程锁的不是同一对象。 
  6.SharedPreferences可靠性下降; SharedPreferences底层是通过读/写XML文件实现的,并发写可能会出问题,所以它不支持多个进程同时去执行写操作,否则会导致一定几率的数据丢失。 
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值