Android中的多线程

说到多线程我们必须知道什么是线程?

一:传统线程机制

什么是线程?

线程是一条程序执行的线索,一行一行代码按时间执行下去,所执行的路线就是一条线程。如果还有另外线索同时执行,也就是两行并行执行,这就是多线程

创建线程的方式

创建线程的第一种方式:继承Thread类

步骤:(1)定义类继承Thread

(2)覆写Thread类中的run方法

(3)调用线程的start方法,该方法两个作用:启动线程,调用run方法

创建线程的第二种方式:实现Runnable接口

步骤:1.定义类实现Runnable接口;

2.覆盖Runnable接口中的run方法,将线程要运行的代码存放在该run方法中

3.通过Thread类建立线程对象;

4.将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。new Thread(t);

5.调用Thread类的start方法开启线程并调用Runnable接口子类的run方法 

实现方式和继承方式有什么区别呢?

实现方式好处:避免了单继承的局限性。在定义线程时,建议使用实现方式。

两种方式区别:

继承Thread线程代码存放Thread子类run方法中

实现Runnable,线程代码存放在接口的子类的run方法

使用多线程机制会提高程序的运行效率吗?

不会,因为多线程都获取到执行权,cup执行到谁就谁执行,必须明确的是:在某一时刻只有一个程序在运行,(多核除外)c pu在做着快速的切换,以达到看上去是同时运行的效果,我们可以形象把多线程的运行行为在互相抢夺cpu的执行权,这就是多 线程的一个特性:随机性。即谁抢到谁执行,至于运行时间cpu说了算。

为什么会有多线程下载?

多线程运行效率并不会快,但是多线程会抢带宽,假如一个线程是10k/s 但是假如我开启20个线程,那样就是200k/s了,这样 下载就快了。


那么就下来我们讲下Android中的多线程,那么Android中的多线程实现是怎么实现的呢?

有以下几种实现方式:

1)Activity.runOnUiThread(Runnable)
2)View.post(Runnable) ;
View.postDelay(Runnable , long)
3)Handler+Message形式
4)AsyncTask

Android是单线程模型,这意味着Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行,所以你单纯的new一个Thread并且start()是不行的,因为这违背了A ndroid的单线程模型。

事件处理的原则:所有可能耗时的操作都放到其他线程去处理。

Android中的Main线程的事件处理不能太耗时,否则后续的事件无法在5秒内得到响应,就会弹出ANR对话框。那么哪些方法会在 Main线程执行呢?

(1)Android的生命周期方法 onCreate() onStart() onResume() onPause() onStop() onDestory()

(2)事件的处理方法 onClick() onItemClick()等。

 当用户与你的应用交互时,事件处理方法的执行快慢决定了应用的响应性是否良好,一般分为同步和异步两种情况:

1) 同步,需要等待返回结果。例如用户点击了注册按钮,需要等待服务端返回结果,那么需要有一个进度条来提示用户你的程序正在运行没有死掉。一般与服务端交互的都要有进度条,例如系统自带的浏览器,URL跳转时会有进度条。
  2) 异步,不需要等待返回结果。例如微博中的收藏功能,点击完收藏按钮后是否成功执行完成后告诉我就行了,我不想等它,这里最好实现为异步的。
  无论同步异步,事件处理都可能比较耗时,那么需要放到其他线程中处理,等处理完成后,再通知界面刷新。

在Android中有多种方法可以实现其他线程与Main线程通讯,我们这里介绍常见的两种。
  1) 使用AsyncTask
  AsyncTask是Android框架提供的异步处理的辅助类,它可以实现耗时操作在其他线程执行,而处理结果在Main线程执行,对于开发 者而言,它屏蔽掉了多线程和后面要讲的Handler的概念。你不了解怎么处理线程间通讯也没有关系,AsyncTask体贴的帮你做好了。使用他你会发 现你的代码很容易被理解,因为他们都有一些具有特定职责的方法,尤其是AsyncTask,有预处理的方法onPreExecute,有后台执行任务的方 法doInBackground,有更新进度的方法publishProgress,有返回结果的方法onPostExecute等等,这就不像post 这些方法,把所有的操作都写在一个Runnable里。不过封装越好越高级的API,对初级程序员反而越不利,就是你不了解它的原理。当你需要面对更加复 杂的情况,而高级API无法完成得很好时,你就杯具了。所以,我们也要掌握功能更强大,更自由的与Main线程通讯的方法:Handler的使用。

可以开启一个多线程执行任务,并且多线程的数据传递也是有这个类自己完成。实际上AsyncTask 是由 thread + handler的封装实现。所以AsyncTask 跟Thread+handler+Message实现没有本质的差别。AsyncTask的代码更少,使用比Thread+handler简单。

主要有    onPreExecute() ; 是指在执行多线程任务之前的一个初始化执行。在UI线程调用

      doInBackground(Params... params);这个方法是AsyncTask新启动的线程实现的。在新线程调用
   onPostExecute(Result result) ;这个是doInBackground()方法执行完成后,才调用的方法。

result 就是doInBackground()的结果,就是用Hanlder的方式传递的数据。这个方法在UI线程调用
     protected void onProgressUpdate(Progress... values);处理中间数据。doInBackGround()方法中,即在新开的线程中调用publishProgress方法,那么hanlder就把publishProgress的值传递到UI线程中。

并且把值交给onProgressUpdate方法处理。所以onProgressUpdate是在UI线程调用的






2)Handler

handler机制,就要设计到5个类,Handler、MessageQueue、Looper、Thread、还有一个Message;

Message是消息,它由MessageQueue统一列队,由Handler处理。

Handler是处理者,他负责发送和处理Message消息。

MessageQueue指消息队列,它用来存放Handler发送过来的队列,并且按照先入先出的规则执行。

Looper的作用就像抽水的水泵,它不断的从MessageQueue中去抽取Message并执行。

Thread线程,是消息循环的执行场所。


知道了这几个类就可以说说消息机制的原理了,在创建Activity之前,当系统启动的时候,先加载ActivityThread这个类,在这个类的main函数中,调用Looper.prepareMainLooper()进行初始化Looper对象,然后创建主线程的handler对象,随后才创建ActivityThread对象,最后调用Looper.loop()方法,不断的进行轮询消息队列中的消息。也就是说,在ActivityThread和Activity创建之前,就已经开启了Looper的loop()方法,不断的进行轮询消息。

handler机制的原理:


我们通过Message.obtain()准备消息数据之后,
第一步是使用sendMessage():通过Handler将消息发送给消息队列
第二步、在发送消息的时候,使用message.target=this为handler发送的message贴上当前handler的标签
第三步、开启HandlerThread线程,执行run方法。
4、在HandlerThread类的run方法中开启轮询器进行轮询:调用Looper.loop()方法进行轮询消息队列的消息
5、在消息队列MessageQueue中enqueueMessage(Message msg, long when)方法里,对消息进行入列,即依据传入的时间进行消息入列(排队)
6、轮询消息:与此同时,Looper在不断的轮询消息队列
7、在Looper.loop()方法中,获取到MessageQueue对象后,从中取出消息(Message msg = queue.next()),如果没有消息会堵塞
8、分发消息:从消息队列中取出消息后,调用 msg.target.dispatchMessage(msg);进行分发消息
9、将处理好的消息分发给指定的handler处理,即调用了handler的 dispatchMessage(msg)方法进行分发消息。
10、在创建handler时,复写的handleMessage方法中进行消息的处理
11、回收消息:在消息使用完毕后,在Looper.loop()方法中调用msg.recycle(),将消息进行回收,即将消息的所有字段恢复为初始状态。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值