背景

在理解了多线程的基础概念之后,接下来就学习下怎么使用多线程开发。

下图时多线程开发的分类,分为基础使用、复合使用、高级使用。

基础使用

1,继承Thread类

简介:Thread类是Java中实现多线程的具体类,封装了所需线程操作。

线程对象和运行线程的区别

线程对象是运行线程的实体,用来控制线程行为的唯一方式,线程对象通过线程类实例化创建,负责控制线程的状态,如运行,睡眠,停止。

优点:实现简单,只需要继承Thread类和复写run()就可以实现多线程操作。

常规使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.tuanzhiriji.androidstudy.thread;

import android.util.Log;
//1,创建线程类(继承自Thread)
public class MyThread extends Thread{
private static final String TAG = "MyThread";
//2,复写run()
@Override
public void run() {
super.run();
//定义线程的行为
for(int i = 0; i < 10; i++){
Log.e(TAG, "run--->" + i);
}
}
}

//3,创建线程对象(实例化对象)
MyThread myThread = new MyThread();
//4,通过线程对象控制线程的状态,运行、睡眠等等。
myThread.start();

匿名类使用

1
2
3
4
5
6
7
8
9
new Thread("test"){
@Override
public void run() {
super.run();
for(int i = 0; i < 10; i++){
Log.e("TAG", "run--->"+i);
}
}
}.start();

下面的图片是他俩的区别

2,Runnable接口

简介:Runnable是一个与多线程相关的抽象接口,他只定义一个方法run(),在Android开发中用于实现多线程。

Runnable可被多个线程(Thread实例)共享,它适合多线程处理同一资源的情况。

一个类可以继承多个接口,避免了继承Thread类而导致的单继承类型

补充一个小知识点

接口和继承的区别

  1. 关键字:接口(interface), 继承(extends)
  2. 定义:接口(对功能的描述), 继承(具体描述一种类)
  3. 结构:接口(接口只能定于全局常量、抽象方法),继承(继承可以定义属性方法、常量、变量等)
  4. 接口可以实现多继承,继承只能单继承
  5. 实现接口的类一定要实现接口的抽象方法,继承的类可以调用、重载父类的任意方法。

常规使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.tuanzhiriji.androidstudy.thread;

import android.util.Log;
//1,创建线程辅助类,实现Runnable接口
public class MyThread extends Thread{
private static final String TAG = "MyThread";
@Override
//2,复写run
public void run() {
super.run();
//定义线程的行为
for(int i = 0; i < 10; i++){
Log.e(TAG, "run--->" + i);
}
}
}
//3,创建线程辅助对象(实例化线程辅助类)
MyRunnable myRunnable = new MyRunnable();
//4,创建线程对象(实例化线程类)
//创建时通过Thread类的构造函数传入线程辅助类对象
//原因:Runnable接口没有对线程的支持,所以必须创建线程类的实例,从、 Thread类的一个实例内部运行。
Thread td = new Thread(myRunnable);
//实现线程操作
td.start();

  1. Java中能真正创建新线程的只有Thread类对象。
  2. 通过实现Runnable的方式,最终还是通过Thread类对象来创建线程,所以对于实现了Runnable接口的类称之为线程辅助类,Thread类才是真正的线程类。

匿名类使用

1
2
3
4
5
6
7
8
9
10
Runnable runnable = new Runnable() {
@Override
public void run() {
for(int i = 0; i < 10; i++){
Log.e(TAG, "run-->"+i);
}
}
};
Thread thread = new Thread(runnable);
thread.start();

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

3,Hanlder

简介:Handler机制是一套Android消息传递机制,在Android开发多线程的应用场景中,将工作线程中需要更新UI的操作信息传递到UI主线程,从而实现工作线程对UI的更新处理,最终实现异步消息的处理。

在Android开发中,为了UI操作是线程安全的,规定了只允许主线程更新Activity里的UI组件,但在实际开发中,存在多个线程并发操作UI组件的情况,导致了UI操作线程不安全,所以采用Handler消息传递机制,在工作线程需要更新UI时,通过Handler通知主线程,从而在主线程中更新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
33
34
private static final int UPDATA_TEXT = 1;
private Handler handler;

//1,在主线程中通过匿名内部类创建Handler类对象
handler = new Handler(){
@Override
//通过复写handleMessage()从而更新UI的操作
public void handleMessage(Message msg) {
//需要执行的UI操作
switch (msg.what){
case UPDATA_TEXT:
text1.setText("nice to meet you");
break;
default:
break;
}
}
};

toB.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new Thread(new Runnable() {
@Override
public void run() {
//2,创建消息对象
Message message = new Message();
message.what = UPDATA_TEXT;
//3,在工作线程中通过Handler发送消息到消息队列中
handler.sendMessage(message);
}
}).start();
}
});

复合使用

1,AsyncTask

简介:是一个Android已封装好的轻量级异步类,属于抽象类,使用时需要实现子类,用于实现多线程,即将工作线程的结果传递给主线程,从而在主线程中指向相关UI操作。

不需要使用Thread+Handler的组合,方便实现异步通信。

采用线程池的缓存线程+复用线程,避免了频繁创建线程和销毁线程所带来的系统资源开销。

核心方法

方法的执行顺序

具体使用

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
public class ExampleAsyncTask extends AppCompatActivity {

private Button mBtnStart;
private Button mBtnQuit;
private ProgressBar mProgressBar;
private TextView mTxtProgress;
private static final String TAG = "ExampleAsyncTask";
private mAsyncTask task;

@Override
protected void onCreate(@Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_example_async_task);
initView();
//2,创建AsyncTask的实例对象
task = new mAsyncTask();

mBtnQuit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
task.cancel(true);
}
});

mBtnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//3,调用子类实例对象的excute方法,执行异步任务
task.execute("1");
}
});
}

private void initView() {
mBtnStart = (Button) findViewById(R.id.mBtnStart);
mBtnQuit = (Button) findViewById(R.id.mBtnQuit);
mProgressBar = (ProgressBar) findViewById(R.id.mProgressBar);
mTxtProgress = (TextView) findViewById(R.id.mTxtProgress);
}

private void showToast(String s){
Toast.makeText(ExampleAsyncTask.this, s, Toast.LENGTH_LONG).show();
}

//1,创建AsyncTask的子类,并且根据需要复写相关的方法
class mAsyncTask extends AsyncTask<String, Integer, String>{

int count = 0;


//UI线程执行
@Override
protected void onPreExecute() {
Log.e(TAG, "onPreExecute");
}

//子线程执行
//strings就是task.execute("1")中传入的参数
@Override
protected String doInBackground(String... strings) {
try {
while (count < 100){
Log.e(TAG, "doInBackground---->" + count);
count++;
publishProgress(count);
Thread.sleep(50);
}
} catch (InterruptedException e){
e.printStackTrace();
}

return null;
}

//UI线程执行
@Override
protected void onProgressUpdate(Integer... values) {
mProgressBar.setProgress(values[0]);
mTxtProgress.setText("loading..." + values[0]+"%");
}

//UI线程执行

@Override
protected void onPostExecute(String s) {
showToast("完成");
}

@Override
protected void onCancelled() {
mTxtProgress.setText("已取消");
mProgressBar.setProgress(0);
}
}

}

2,HandlerThread

简介:HandlerThread是一个Android已经封装好的轻量级异步类,用于实现多线程从而保证线程安全。

HandlerThread本质是通过继承Thread类和封装Handler类的使用,从而创建新线程和与其他线程进行通信变得更加方便,也不需要使用Thread+Handler的复杂组合。

工作原理:Thread类 + Handler类机制

  1. 通过继承Thread类,快速创建一个带有Looper对象的新工作线程
  2. 通过封装Handler类,快速创建Handler与其他线程进行通信

具体使用

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package com.tuanzhiriji.androidstudy.thread;

import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import com.tuanzhiriji.androidstudy.R;

public class MyHandlerThread extends AppCompatActivity {

private static final String TAG = "MyHandlerThread";
private TextView text;
private Button mBtnHandlerThread;
private Button mBtnQuit;
private Button mBtnInnerClass;
//1,创建HandlerThread实例对象 传入参数(给线程一个名字)的目的就是为了标记该线程
private HandlerThread mHandlerThread = new HandlerThread("mHandlerThread");

//创建与主线程相关联的Handler
private Handler myHandler = new Handler();
/*private Handler mHandlerInnerClass = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 1:
text.setText("点击了mBtnInnerClass");
break;
case 2:
text.setText("来自于mHandlerInHandlerThread的请求更新");
break;
}
}
};*/

@Override
protected void onCreate(@Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler_thread);
initView();
//2,启动线程
mHandlerThread.start();

//3,创建工作Handler以及复写handleMessage
//作用:关联HandlerThread的Lopper对象、实现消息处理操作,与其他进程通信
final Handler mHandlerInHandlerThread = new Handler(mHandlerThread.getLooper()){
@Override
public void handleMessage(@NonNull Message msg) {
switch (msg.what){
case 1:
try {
Thread.sleep(100);
} catch (InterruptedException e){
e.printStackTrace();
}
//通过主线程Handler.post方法进行主线程的UI更新操作
myHandler.post(new Runnable() {
@Override
public void run() {
text.setText("点击了mBtnInnerClass");
}
});
break;
case 2:
try {
Thread.sleep(300);
} catch (InterruptedException e){
e.printStackTrace();
}
myHandler.post(new Runnable() {
@Override
public void run() {
text.setText("点击了mBtnHandlerThread");
}
});
break;

}
/* try {
Thread.sleep(100);
} catch (Exception e){
e.getMessage();
}
Message msg1 = Message.obtain();
msg1.what = 2;
mHandlerInnerClass.sendMessage(msg1);
super.handleMessage(msg);*/
}
};

mBtnQuit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mHandlerThread.quit();
}
});

//使用工作线程Handler向工作线程的消息队列发送消息
mBtnHandlerThread.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//定义发送的消息
Message message = Message.obtain();
//消息的标识
message.what = 2;
//消息的存放
message.obj = "A";
//通过Handler发送消息到其绑定的消息队列
mHandlerInHandlerThread.sendMessage(message);
}
});

mBtnInnerClass.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Message message = Message.obtain();
message.what = 1;
message.obj = "B";
mHandlerInHandlerThread.sendMessage(message);
/*new Thread(new Runnable() {
@Override
public void run() {
Message msg = Message.obtain();
msg.what = 1;
mHandlerInnerClass.sendMessage(msg);
}
}).start();*/
}
});

}

private void initView() {
text = (TextView) findViewById(R.id.text);
mBtnHandlerThread = (Button) findViewById(R.id.mBtnHandlerThread);
mBtnQuit = (Button) findViewById(R.id.mBtnQuit);
mBtnInnerClass = (Button) findViewById(R.id.mBtnInnerClass);
}
}

3,IntentService

简介:Android里的一个封装类,继承了四大组件之一的Service,用于处理异步请求和实现多线程,线程任务需按照顺序在后台执行。适用于离线下载,不符合多个数据同时请求的场景,所有的任务都在同一个Thread Looper里执行。

在定义完IntentService的子类之后需要在Manifest.xml注册服务

具体使用

步骤一:定义 IntentService的子类

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package com.tuanzhiriji.androidstudy.thread;

import android.app.IntentService;
import android.content.Intent;
import android.util.Log;

import androidx.annotation.Nullable;

public class MyIntentService extends IntentService {
private static final String TAG = "MyIntentService";
/**
* @deprecated
*/
//在构造函数中传入线程的名字
public MyIntentService() {
super("MyIntentService");
}


//根据Intent实现耗时任务操作
@Override
protected void onHandleIntent(@Nullable Intent intent) {
String taskName = intent.getExtras().getString("taskName");
switch (taskName){
case "task1":
Log.e(TAG, "MyIntnetService--->do task1");
break;
case "task2":
Log.e(TAG, "MyIntentService--->do task2");
break;
default:
break;
}
}

@Override
public void onCreate() {
Log.e(TAG, "MyIntentService----> onCreate");
super.onCreate();

}

//将请求的Intent添加到队列中去(默认实现)
@Override
public int onStartCommand(@Nullable @org.jetbrains.annotations.Nullable Intent intent, int flags, int startId) {
Log.e(TAG, "MyIntentService--->onStartCommand");
return super.onStartCommand(intent, flags, startId);

}

@Override
public void onDestroy() {
Log.e(TAG, "MyIntentService--->onDestroy");
super.onDestroy();
}
}

步骤二:在Manifest.xml中注册服务

1
<service android:name=".thread.MyIntentService" />

步骤三:在Activity中开启Service服务

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
package com.tuanzhiriji.androidstudy.thread;

import android.content.Intent;
import android.os.Bundle;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import com.tuanzhiriji.androidstudy.R;

public class MyIntentServiceActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_intentservice_activity);

//请求1
Intent intent1 = new Intent(this, MyIntentService.class);
Bundle bundle1 = new Bundle();
bundle1.putString("taskName", "task1");
intent1.putExtras(bundle1);
startService(intent1);

//请求2
Intent intent2 = new Intent(this, MyIntentService.class);
Bundle bundle2 = new Bundle();
bundle2.putString("taskName", "task2");
intent2.putExtras(bundle2);
startService(intent2);

//重复启动
startService(intent1);
}
}