Android跨线程、进程通信,主线程与子线程通信

时间:2021-08-06 05:12:04

> Android多线程的四种方式: 1.Handler+Thread; 2.AsyncTask; 3.ThreadPoolExecutor; 4.IntentService

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

----------------------

进程就相当于工厂,线程就是工厂里的流水线,线程不能独立存在,必须存在于进程中。
  多进程:系统中同时存在多个并行的进程,则称为多进程。可通过电脑任务管理器查看正在运行的进程,比如用电脑聊QQ的同时看电影,就是多进程的体现。 
  多线程:线程是进程中的单个顺序控制流,是一条执行路径,一个进程如果有多条执行路径,则称为多线程。比如给某人聊QQ的同时还可以接收到其他人的消息。

进程间线程间的同步锁原理和种类-- http://blog.csdn.net/blues1021/article/details/44318321
多线程和多进程中避免锁机制注意的几点-- http://www.cnblogs.com/jiangwang2013/p/3398272.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 机制中的两种。


> Android跨进程通信(几种进程通讯):Intent,aidl,messager,content provider,广播

> 跨进程
Android 进程使用 Messenger 通信 使用AIDL实现Android的跨进程通信 使用ContentProvider跨进程共享数据 使用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);  

> 用于实现 后台线程与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不一样的


[纯干货]安卓跨进程点击事件的解决方案-http://mt.sohu.com/20160616/n454754223.shtml