android中实现多线程,Android中通过HandlerThread实现真正的多线程

66b52468c121889b900d4956032f1009.png

8种机械键盘轴体对比

本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

上一篇博客中我在解释Handler的过程中提到了HandlerThread,我们先回顾一下上一篇博客中对于Handler的定义:Handler会关联一个单独的线程和消息队列。Handler默认关联主线程,虽然要提供Runnable参数,但默认是直接调用Runnable中的run()方法。也就是默认下会在主线程执行,如果在这里面的操作会有阻塞,界面也会卡住。

也就是说如果我们使用Handler提供的方法handler.post(new Runnable())时候,如果使用不当的话一样会出现界面卡死,因为其默认管线的还是主线程,也就是说其还是会在主线程中简单地调用Runnable中的run()方法,这样耗时任务虽然在run()方法中,但是还是运行在主线程,所以同样会阻塞UI,接下来我们来看两个例子,就会更明白了,第一个例子:1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33package cn.picksomething.testhandler;

import android.app.Activity;

import android.os.Bundle;

import android.os.Handler;

import android.util.Log;

public class extends Activity{

private String TAG = "TAG";

private Handler handler = new Handler();

protected void onCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState);

handler.post(new myRunnable());

Log.d(TAG, "onCreate-----The thread id is:" + Thread.currentThread().getId());

setContentView(R.layout.main);

}

class myRunnable implements Runnable{

public void run(){

Log.d(TAG, "run method is calling----");

Log.d(TAG, "The thread id is:" + Thread.currentThread().getId());

try {

Thread.sleep(6000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

运行上述程序,程序启动6秒之后,才看到布局被加载,显示出TextView上的Hello World!字样

分析一下程序执行的过程,首先程序启动,就把myRunnable加入到当前线程的消息队列中,也就是handler默认关联的主线程消息队列,android的handler确实是异步机制,所以在handler.post(new myRunnable());之后,程序会继续执行,所以以后的语句会继续执行,会输出onCreate中的当前线程ID。但同时myRunnable()的run方法也在运行,一样输出run方法中的当前线程ID,然后让当前线程休眠6秒

通过输出结果和分析,我们可以得出handler和主线程是同一个线程,handler也是运行在主线程中的,这个时候若是执行耗时任务,显然会阻塞UI。当然肯定有解决办法的:

Android给我们提供了Looper这样一个类,上一遍博客中已经介绍过了,Android中每一个Thread都跟着一个Looper,Looper可以帮助Thread维护一个消息队列,每个Thread都只有一个消息队列。我们看看另一个例子:1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38package cn.picksomething.testlooper;

import android.os.Bundle;

import android.os.Handler;

import android.os.HandlerThread;

import android.app.Activity;

import android.util.Log;

public class extends Activity{

private String TAG = "TAG";

private Handler handler = null;

protected void onCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState);

HandlerThread mThread = new HandlerThread("handlerThread");

mThread.start();

handler = new Handler(mThread.getLooper());

handler.post(new myRunnable());

Log.d(TAG, "onCreate-----The Thread id is: " + Thread.currentThread().getId());

setContentView(R.layout.main);

}

class myRunnable implements Runnable{

public void run(){

Log.d(TAG, "myRunnable is running----");

Log.d(TAG, "The thread id is: " + Thread.currentThread().getId());

try {

Thread.sleep(6000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

运行上述程序,过滤打印信息,我们看到LogCat输出如下结果:1

2

3onCreate-----The Thread id is: xxx

myRunnable is running----

The thread id is: xxx

同时我们看到程序已启动,就立即输出了布局文件中的Hello world!信息。

在这个例子中,用到了HandlerThread,在HandlerThread对象中可以通过getLooper方法获取一个Looper对象控制句柄,我们可以将这个Looper对象映射到一个Handler中来实现一个线程同步机制,所以就会有上面的结果了。这样就达到了多线程的效果

补充:HandlerThread这个类,HandlerThread继承于Thread,所以它本质就是个Thread。HandlerThread类用于方便的创建一个含有looper的线程类,looper用来创建handler类。我们一般不创建looper对象,直接调用HandlerThread即可,HandlerThread本身实现了循环处理消息的功能,不用再直接调用Looper.prepare()方法,与普通Thread的差别就在于它有个Looper成员变量,这个Looper其实就是对消息队列以及队列处理逻辑的封装,简单说就是消息队列+消息循环

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值