Android多线程(浅学版)

[TOC]

一、多线程是什么

在 Android 中,多线程是指同时运行多个线程,每个线程独立执行自己的任务。Android 应用通常运行在主线程(也称为 UI 线程)中,负责处理用户界面的更新和事件响应。然而,有些操作,例如网络请求、耗时计算等,如果在主线程中执行,会阻塞UI响应,导致应用无响应或者卡顿。

为了避免这种情况,开发者可以使用多线程来进行后台任务的处理,从而将耗时的操作放在单独的线程中执行,保持主线程的流畅性和响应性。这样用户就可以在应用执行耗时任务的同时继续与应用进行交互。

多线程可以提高应用的性能和响应速度,有效地实现异步操作、并发处理和任务分发。同时,合理地使用多线程也可以避免主线程被阻塞,提高应用的稳定性和用户体验。

需要注意的是,在进行多线程编程时需要注意线程同步、资源共享等问题,以避免出现竞态条件和其他线程相关的问题。

二、多线程有几种实现方式

这里对多线程分为简单使用复杂使用高级使用

简单使用

  • 继承Thread类
  • 实现Runnable接口
  • Handler

复杂使用

  • AsyncTask
  • HandlerThread
  • IntentService

高级使用

线程池(ThreadPool)
本文主要讲解的是多线程的简单使用,关于复杂使用,就不作展示了。复杂使用实则也是用几种简单实现的方式实现的,只不过在简单实现的基础上实现了优化。

三、代码实战

3.1继承Thread

1
2
3
4
5
6
7
8
9
public class MyThread extends Thread{
@Override
public void run() {
super.run();
for(int i = 0 ;i <100; i++){
System.out.println("线程名字:"+getName()+"---"+i);
}
}
}

这是自己编写的一个类继承Thread并重写run方法,使用方法如下:

1
2
3
MyThread myThread = new MyThread();

myThread.start();

通过MyThread类实例以后调用start函数即可实现。

缺点:如果继承了Thread以后就不可以继承其他的类了,即单继承。

3.2Thread匿名实现

1
2
3
4
5
6
7
new Thread(){
@Override
public void run() {
super.run();
System.out.println("我是Thread的匿名实现");
}
}.start();

直接采用匿名类的方式创建然后复写run方法即可实现简单方便快捷,缺点,每次实现都需要重新编写run方法。

常规方式即继承Thread和匿名Thread实现的对比

3.3实现Runnable接口

1
2
3
4
5
6
public class MyThreadRunnable implements Runnable{
@Override
public void run() {
System.out.println("线程名字:"+this.getClass().getName()+"---"+i);
}
}

编写MyThreadRunnable并实现Runnable接口,然后复写run方法即可实现。

虽然这里是通过实现Runnable接口实现多线程,但是实现Runnable的方式,最终还是通过Thread类对象来创建线程,即实现了Runnable接口的类,称为线程辅助类;Thread类才是真正的线程类

3.4Runnable匿名实现

1
2
3
4
5
6
7
8
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("我是匿名Runnable");
}
};
Thread thread = new Thread(runnable);
thread.start();

首先创建Runnable的实例,然后创建Thread的实例并把runnable当做参数传入最后调用thread.start方法即可使用。

常规实现即用Runnable接口和匿名实现的对比如下

下面是继承Thread类和实现Runnable接口的对比

3.5Handler.sendMessage()

Handler的介绍

上面应该是比较常见的两种实现多线程的方式,而这里是通过Handle来实现的,可能有人会问,为什么android多线程的需要handle?handle有什么作用?其实handle大有作为了,它不仅可以作为信息传递的媒介和好帮手,同时也是多线程的一把好手。

在 Android 中,多线程编程通常涉及到线程之间的通信和消息传递。Handler 是 Android 提供的一个机制,用于线程之间的消息传递和处理。

以下是 Handler 的几个主要作用:

  • 线程间通信:在多线程编程中,我们可能需要在一个线程中触发另一个线程执行某些任务。通过 Handler,我们可以发送消息或者 post Runnable 到目标线程的消息队列中,从而实现线程间的通信。
  • 消息处理:Handler 可以用来接收和处理消息。当有消息到达线程的消息队列时,Handler 会将消息取出并根据需要进行处理。这样可以方便地在特定的线程中执行相应操作,例如更新 UI、执行耗时操作等。
  • 定时任务:Handler 可以与定时器 Timer 结合使用,实现定时任务。通过发送延迟消息或周期性消息,我们可以在指定的时间间隔内执行特定的任务,从而实现定时功能。
  • 主线程操作:在 Android 中,UI 操作必须在主线程(UI 线程)上执行。通过在主线程中创建 Handler,并将其与 Looper 关联,就可以在其他线程中发送消息到主线程的消息队列中,从而实现在主线程上执行操作,例如更新 UI 界面。

总之,Handler 在 Android 多线程编程中起着关键的作用,它提供了一种安全、方便的线程间通信和消息处理机制,使得在多线程环境下更容易实现任务调度和UI操作。

有关Handler的相关基本调用说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

public class MyHandle extends Handler{
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
System.out.println(msg);
}
}
myHandle = new MyHandle();
Message message = Message.obtain();
message.what=1;
message.obj = "我是Handle的Obj";
myHandle.sendMessage(message);
msg.what 消息标识
msg.obj 消息内容存放

这里是对Handler类的继承然后复写handleMessage方法来实现的。通过实例化MyHandle类并实例化Message,然后设置message中传递信息的内容以及消息的标识,最后调用sendMessage发送消息。

当然,上面都有匿名实现,handler也是有的。

1
2
3
4
5
6
7
8
9
10
private Handler handler = new Handler(){
@Override
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
return super.sendMessageAtTime(msg, uptimeMillis);
}
};
Message message = Message.obtain();
message.what=1;
message.obj = "内容填写";
handle.sendMessage(message);

3.6Handler.post()

1
2
3
4
5
6
7
myHandle.post(new MyRunnable(){
@Override
public void run() {
super.run();
System.out.println("Handle.post的使用方法");
}
});

这里和上面一样需要实例化一个Handler,当然你会说,都需要通过继承handler实现,那这二者是不是不一样呢?其实看过源码你会发现,二者还是有区别的,在底层会检查你是通过sendmessage方法实现的还是通过post实现的,根据你实现的方式会去调用不一样的方法来实现的。

这里是二者的一个大概对比

另外,如果是学习android这块的,面试好像经常会问有关Handler的知识。


Android多线程(浅学版)
https://crwei996.github.io/2023/09/22/Android多线程-浅学版/
Author
Crwei996
Posted on
September 22, 2023
Licensed under