前言
在 Android 开发中, 多线程的使用十分常见
今天, 我将全面解析多线程其中一种常见用法: 继承 Thread 类.
目录
示意图
1. 简介
示意图
2. 使用讲解
2.1 使用步骤
示意图
2.2 具体使用
// 步骤 1: 创建线程类 (继承自 Thread 类)
class MyThread extends Thread{
// 步骤 2: 复写 run(), 内容 = 定义线程行为
@Override
public void run(){
... // 定义的线程行为
}
}
// 步骤 3: 创建线程对象, 即 实例化线程类
MyThread mt=new MyThread("线程名称");
// 步骤 4: 通过 线程对象 控制线程的状态, 如 运行, 睡眠, 挂起 / 停止
// 此处采用 start() 开启线程
mt.start();
2.3 简便使用: 匿名类
很多情况下, 开发者会选择一种更加方便的方法去创建线程: 匿名类
// 步骤 1: 采用匿名类, 直接 创建 线程类的实例
new Thread("线程名称") {
// 步骤 2: 复写 run(), 内容 = 定义线程行为
@Override
public void run() {
// 步骤 3: 通过 线程对象 控制线程的状态, 如 运行, 睡眠, 挂起 / 停止
}.start();
2.3 区别
2 种方法本质相同, 但是各有优劣势 & 不同的应用场景:
大家可根据自己的需求场景来选择具体的使用方法
示意图
为了让大家理解更加深刻, 下面例子我都会采用方法 1 = 常规方式 来演示
3. 实例应用
实例 1
应用场景: 创建两个线程 - 实现两个相同的耗时任务
实例说明: 实现 2 个窗口同时卖火车票; 每个窗口卖 100 张, 卖票速度都是 1s / 张
建议先下载 Demo 再看分析: Carson_Ho 的 Github 地址: 多线程之继承 Thread 类
具体实现
main_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.carson_ho.demoforthread.MainActivity">
// 设置一个按钮用以启动卖票
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="点击开始卖票"
android:layout_centerInParent="true"
/>
</RelativeLayout>
MainActivity.java
package com.example.carson_ho.demoforthread;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
// 主布局中定义了一个按钮用以启动线程
Button button;
// 步骤 1: 创建线程类, 继承自 Thread 类
private class MyThread extends Thread{
private int ticket = 100;// 一个窗口有 100 张票
private String name; // 窗口名, 也即是线程的名字
public MyThread(String name){
this.name=name;
}
// 在 run 方法里复写需要进行的操作
@Override
public void run(){
while (ticket>0){
ticket--;
System.out.println(name + "卖掉了 1 张票, 剩余票数为:"+ticket);
try {
Thread.sleep(1000);// 卖票速度是 1s 一张
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Button 按下时会开启一个新线程执行卖票
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 步骤 2: 创建线程类的实例
// 创建二个线程, 模拟二个窗口卖票
MyThread mt1 = new MyThread("窗口 1");
MyThread mt2 = new MyThread("窗口 2");
// 步骤 3: 调用 start() 方法开启线程
// 启动二个线程, 也即是窗口, 开始卖票
mt1.start();
mt2.start();
}
});
}
}
测试结果
结果展示
Demo 源码地址
Demo for Thread example1
实例 2
应用场景: 创建两个线程 - 实现两个不同的耗时任务
实例说明: 实现 2 个窗口同时卖火车票; 每个窗口卖 100 张, 但卖票速度不同: 窗口 1 是 1s / 张, 窗口 2 是 3s / 张
建议先下载 Demo 再看分析: Carson_Ho 的 Github 地址: 多线程之继承 Thread 类
具体实现
main_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.carson_ho.demoforthread_2.MainActivity">
// 设置一个按钮以启动卖票
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="点击开始卖票" />
</RelativeLayout>
MainActivity.java
package com.example.carson_ho.demoforthread_2;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
// 主布局中定义了一个按钮用以启动线程
Button button;
// 步骤 1: 创建线程类, 继承自 Thread 类
// 因为这里需要有两个操作: 一个窗口卖票速度是 1s / 张, 一个窗口是 3s / 张
// 所以需要创建两个 Thread 的子类
// 第一个 Thread 子类实现一个窗口卖票速度是 1s / 张
private class MyThread1 extends Thread{
private int ticket = 100;// 一个窗口有 100 张票
private String name; // 窗口名, 也即是线程的名字
public MyThread1(String name){
this.name=name;
}
// 在 run 方法里复写需要进行的操作: 卖票速度是 1s / 张
@Override
public void run(){
while (ticket>0){
ticket--;
System.out.println(name + "卖掉了 1 张票, 剩余票数为:"+ticket);
try {
Thread.sleep(1000);// 卖票速度是 1s 一张
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// 第二个 Thread 子类实现一个窗口卖票速度是 3s / 张
private class MyThread2 extends Thread{
private int ticket = 100;// 一个窗口有 100 张票
private String name; // 窗口名, 也即是线程的名字
public MyThread2(String name){
this.name=name;
}
// 在 run 方法里复写需要进行的操作: 卖票速度是 3s / 张
@Override
public void run(){
while (ticket>0){
ticket--;
System.out.println(name + "卖掉了 1 张票, 剩余票数为:"+ticket);
try {
Thread.sleep(3000);// 卖票速度是 1s 一张
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Button 按下时会开启一个新线程执行卖票
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 步骤 2: 创建线程类的实例
// 创建二个线程, 模拟二个窗口卖票
MyThread1 mt1 = new MyThread1("窗口 1");
MyThread2 mt2 = new MyThread2("窗口 2");
// 步骤 3: 调用 start() 方法开启线程
// 启动二个线程, 也即是窗口, 开始卖票
mt1.start();
mt2.start();
}
});
}
}
测试结果 由于卖票速度不同, 所以窗口 1 卖 3 张时, 窗口 2 才卖 1 张.
Thread2.png
Demo 源码地址
Carson_Ho 的 Github 地址: 多线程之继承 Thread 类
4. 与 "实现 Runnable 接口" 对比
在 Java 中, 继承 Thread 类和实现 Runnable 接口是实现多线程最常用的 2 种方法
今天我们就来对比下这两种方法
若你还不熟悉实现 Runnable 接口, 建议你先去看
Android 多线程: 实现 Runnable 接口 使用解析 (含实例教程)
示意图
5. 总结
本文主要对多线程中继承 Thread 类的用法进行了全面介绍
接下来, 我会继续讲解 Android 开发中关于多线程的知识, 具体包括 Runnable,Handler,HandlerThread 等等, 有兴趣可以继续关注 Carson_Ho 的安卓开发笔记
请点赞! 因为你的鼓励是我写作的最大动力!
来源: https://juejin.im/entry/5a711e9df265da3e274578df