前言
- 在
Android
開發(fā)中,多線程的使用十分常見 - 今天端铛,我將全面解析多線程其中一種常見用法:
Runnable
接口
Carson帶你學(xué)多線程系列
基礎(chǔ)匯總
Android多線程:基礎(chǔ)知識匯總
基礎(chǔ)使用
Android多線程:繼承Thread類使用(含實(shí)例教程)
Android多線程:實(shí)現(xiàn)Runnable接口使用(含實(shí)例教程)
復(fù)合使用
Android 多線程:AsyncTask使用教程(含實(shí)例講解)
Android 多線程:AsyncTask原理及源碼分析
Android多線程:HandlerThread使用教程(含實(shí)例講解)
Android多線程:HandlerThread原理及源碼分析
Android多線程:IntentService使用教程(含實(shí)例講解)
Android多線程:IntentService的原理及源碼分析
Android多線程:線程池ThreadPool全方位教學(xué)
相關(guān)使用
Android異步通信:這是一份全面&詳細(xì)的Handler機(jī)制學(xué)習(xí)攻略
Android多線程:手把手教你全面學(xué)習(xí)神秘的Synchronized關(guān)鍵字
Android多線程:帶你了解神秘的線程變量 ThreadLocal
目錄
1. 簡介
2. 使用步驟
2.1 常規(guī)使用
// 步驟1:創(chuàng)建線程輔助類孕锄,實(shí)現(xiàn)Runnable接口
class MyThread implements Runnable{
....
@Override
// 步驟2:復(fù)寫run()崇败,定義線程行為
public void run(){
}
}
// 步驟3:創(chuàng)建線程輔助對象菌瘫,即 實(shí)例化 線程輔助類
MyThread mt=new MyThread();
// 步驟4:創(chuàng)建線程對象熊户,即 實(shí)例化線程類途事;線程類 = Thread類溺忧;
// 創(chuàng)建時(shí)通過Thread類的構(gòu)造函數(shù)傳入線程輔助類對象
// 原因:Runnable接口并沒有任何對線程的支持咏连,我們必須創(chuàng)建線程類(Thread類)的實(shí)例,從Thread類的一個(gè)實(shí)例內(nèi)部運(yùn)行
Thread td=new Thread(mt);
// 步驟5:通過 線程對象 控制線程的狀態(tài)鲁森,如 運(yùn)行祟滴、睡眠、掛起 / 停止
// 當(dāng)調(diào)用start()方法時(shí)歌溉,線程對象會(huì)自動(dòng)回調(diào)線程輔助類對象的run()垄懂,從而實(shí)現(xiàn)線程操作
td.start();
特別注意:
-
Java
中真正能創(chuàng)建新線程的只有Thread
類對象 - 通過實(shí)現(xiàn)
Runnable
的方式阱州,最終還是通過Thread
類對象來創(chuàng)建線程
所以對于 實(shí)現(xiàn)了
Runnable
接口的類嚼吞,稱為 線程輔助類;Thread
類才是真正的線程類
2.2 簡便使用:匿名類
很多情況下吸祟,開發(fā)者會(huì)選擇一種更加方便的方法去創(chuàng)建線程:匿名類
// 步驟1:通過匿名類 直接 創(chuàng)建線程輔助對象匙头,即 實(shí)例化 線程輔助類
Runnable mt = new Runnable() {
// 步驟2:復(fù)寫run()漫谷,定義線程行為
@Override
public void run() {
}
};
// 步驟3:創(chuàng)建線程對象,即 實(shí)例化線程類蹂析;線程類 = Thread類舔示;
Thread mt1 = new Thread(mt, "窗口1");
// 步驟4:通過 線程對象 控制線程的狀態(tài),如 運(yùn)行电抚、睡眠惕稻、掛起 / 停止
mt1.start();
2.3 區(qū)別
2種方法本質(zhì)相同,但是各有優(yōu)劣勢 & 不同的應(yīng)用場景:
大家可根據(jù)自己的需求場景來選擇具體的使用方法
為了讓大家理解更加深刻蝙叛,下面例子我都會(huì)采用方法1 = 常規(guī)方式 來演示
3. 實(shí)例應(yīng)用
實(shí)例1
- 應(yīng)用場景:創(chuàng)建兩個(gè)線程-實(shí)現(xiàn)兩個(gè)相同的耗時(shí)任務(wù)
- 實(shí)例說明:實(shí)現(xiàn)2個(gè)窗口同時(shí)賣火車票俺祠;每個(gè)窗口賣100張,賣票速度都是1s/張
建議先下載Demo再看分析:Carson_Ho的Github地址:多線程之繼承Thread類
- 具體實(shí)現(xiàn)
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.demoforrunnable.MainActivity">
//設(shè)置一個(gè)按鈕用以啟動(dòng)線程
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="點(diǎn)擊開始賣票" />
</RelativeLayout>
MainActivity.java
package com.example.carson_ho.demoforrunnable;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
//主布局中定義了一個(gè)按鈕用以啟動(dòng)線程
Button button;
//步驟1:創(chuàng)建線程類借帘,實(shí)現(xiàn)Runnable接口
private class MyThread1 implements Runnable{
private int ticket = 100;//一個(gè)窗口有100張票
//在run方法里復(fù)寫需要進(jìn)行的操作:賣票速度1s/張
@Override
public void run(){
while (ticket>0){
ticket--;
System.out.println(Thread.currentThread().getName() + "賣掉了1張票蜘渣,剩余票數(shù)為:"+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按下時(shí)會(huì)開啟一個(gè)新線程執(zhí)行賣票
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//步驟2:創(chuàng)建線程類的實(shí)例
//創(chuàng)建二個(gè)線程,模擬二個(gè)窗口賣票
MyThread1 mt1 = new MyThread1();
MyThread1 mt2 = new MyThread1();
Thread mt11 = new Thread(mt1, "窗口1");
Thread mt22 = new Thread(mt2, "窗口2");
//步驟3:調(diào)用start()方法開啟線程
//啟動(dòng)二個(gè)線程肺然,也即是窗口宋梧,開始賣票
mt11.start();
mt22.start();
}
});
}
}
- 測試結(jié)果
- Demo源碼地址
Carson_Ho的Github地址:多線程之繼承Thread類
實(shí)例2
- 應(yīng)用場景:創(chuàng)建兩個(gè)線程-實(shí)現(xiàn)兩個(gè)不同的耗時(shí)任務(wù)
- 實(shí)例說明:實(shí)現(xiàn)2個(gè)窗口同時(shí)賣火車票;每個(gè)窗口賣100張狰挡,但賣票速度不同:窗口1是1s/張捂龄,窗口2是3s/張
建議先下載Demo再看分析:Carson_Ho的Github地址:多線程之繼承Thread類
- 具體實(shí)現(xiàn)
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.demoforrunnable2.MainActivity">
//設(shè)置按鈕用以啟動(dòng)線程
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="點(diǎn)擊開始賣票" />
</RelativeLayout>
MainActivity.java
package com.example.carson_ho.demoforrunnable2;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
//主布局中定義了一個(gè)按鈕用以啟動(dòng)線程
Button button;
//步驟1:創(chuàng)建線程類,實(shí)現(xiàn)Runnable接口
//由于需要實(shí)現(xiàn)兩個(gè)不同的操作:賣票速度1s/張和3s/張
//所以需要?jiǎng)?chuàng)建兩個(gè)線程類并實(shí)現(xiàn)Runnable接口
//第一個(gè)線程類:實(shí)現(xiàn)賣票速度1s/張操作
private class MyThread1 implements Runnable{
private int ticket = 100;//一個(gè)窗口有100張票
//在run方法里復(fù)寫需要進(jìn)行的操作:賣票速度1s/張
@Override
public void run(){
while (ticket>0){
ticket--;
System.out.println(Thread.currentThread().getName() + "賣掉了1張票加叁,剩余票數(shù)為:"+ticket);
try {
Thread.sleep(1000);//賣票速度是1s一張
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//第二個(gè)線程類:實(shí)現(xiàn)賣票速度3s/張操作
private class MyThread2 implements Runnable{
private int ticket = 100;//一個(gè)窗口有100張票
//在run方法里復(fù)寫需要進(jìn)行的操作:賣票速度3s/張
@Override
public void run(){
while (ticket>0){
ticket--;
System.out.println(Thread.currentThread().getName() + "賣掉了1張票倦沧,剩余票數(shù)為:"+ticket);
try {
Thread.sleep(3000);//賣票速度是3s一張
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Button按下時(shí)會(huì)開啟一個(gè)新線程執(zhí)行賣票
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//步驟2:創(chuàng)建線程類的實(shí)例
//分別實(shí)例化兩個(gè)線程子類
MyThread1 mt1 = new MyThread1();
MyThread2 mt2 = new MyThread2();
//創(chuàng)建二個(gè)線程,模擬二個(gè)窗口賣票
Thread mt11 = new Thread(mt1, "窗口1");//賣票速度1s/張
Thread mt22 = new Thread(mt2, "窗口2");//賣票速度3s/張
//步驟3:調(diào)用start()方法開啟線程
//啟動(dòng)二個(gè)線程它匕,也即是窗口展融,開始賣票
mt11.start();
mt22.start();
}
});
}
}
-
測試結(jié)果
由于賣票速度不同,所以窗口1賣3張時(shí)豫柬,窗口2才賣1張告希。
- Demo源碼地址
Carson_Ho的Github地址:多線程之繼承Thread類
實(shí)例3
- 應(yīng)用場景:創(chuàng)建兩個(gè)線程-實(shí)現(xiàn)一個(gè)耗時(shí)任務(wù)
- 實(shí)例說明:實(shí)現(xiàn)2個(gè)窗口同時(shí)賣火車票扑浸;兩個(gè)窗口一共賣100張,賣票速度均為1s/張
建議先下載Demo再看分析:Carson_Ho的Github地址:多線程之繼承Thread類
- 具體實(shí)現(xiàn)
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.demoforrunnable3.MainActivity">
//設(shè)置按鈕用以啟動(dòng)線程
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="點(diǎn)擊開始賣票" />
</RelativeLayout>
MainActivity.java
package com.example.carson_ho.demoforrunnable3;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
//主布局中定義了一個(gè)按鈕用以啟動(dòng)線程
Button button;
//步驟1:創(chuàng)建線程類燕偶,實(shí)現(xiàn)Runnable接口
private class MyThread1 implements Runnable{
private int ticket = 100;//兩個(gè)窗口一共要賣100張票
//在run方法里復(fù)寫需要進(jìn)行的操作:賣票速度1s/張
@Override
public void run(){
while (ticket>0){
ticket--;
System.out.println(Thread.currentThread().getName() + "賣掉了1張票喝噪,剩余票數(shù)為:"+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按下時(shí)會(huì)開啟一個(gè)新線程執(zhí)行賣票
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//步驟2:創(chuàng)建線程類的實(shí)例
//因?yàn)槭莾蓚€(gè)窗口共賣100張票,即共用資源
//所以只實(shí)例化一個(gè)實(shí)現(xiàn)了Runnable接口的類
MyThread1 mt = new MyThread1();
//因?yàn)橐獎(jiǎng)?chuàng)建二個(gè)線程,模擬二個(gè)窗口賣票
Thread mt11 = new Thread(mt, "窗口1");
Thread mt12 = new Thread(mt, "窗口2");
//步驟3:調(diào)用start()方法開啟線程
//啟動(dòng)二個(gè)線程指么,也即是窗口酝惧,開始賣票
mt11.start();
mt12.start();
}
});
}
}
-
測試結(jié)果
實(shí)現(xiàn)了兩個(gè)窗口一起賣100張票的目的
Demo源碼地址
Carson_Ho的Github地址:多線程之繼承Thread類
4. 與 “繼承Thread類”對比
- 在
Java
中,繼承Thread
類和實(shí)現(xiàn)Runnable
接口是實(shí)現(xiàn)多線程最常用的2種方法 - 今天我們就來對比下這兩種方法
若還不熟悉 繼承
Thread
類的使用伯诬,請看文章Android多線程:繼承Thread類 使用解析(含實(shí)例教程)
5. 總結(jié)
- 本文主要對多線程中實(shí)現(xiàn)
Runnable
的用法進(jìn)行了全面介紹 - 下一篇文章我將對講解
Android
多線程的相關(guān)知識晚唇,感興趣的同學(xué)可以繼續(xù)關(guān)注Carson_Ho的簡書
Carson帶你學(xué)多線程系列
基礎(chǔ)匯總
Android多線程:基礎(chǔ)知識匯總
基礎(chǔ)使用
Android多線程:繼承Thread類使用(含實(shí)例教程)
Android多線程:實(shí)現(xiàn)Runnable接口使用(含實(shí)例教程)
復(fù)合使用
Android 多線程:AsyncTask使用教程(含實(shí)例講解)
Android 多線程:AsyncTask原理及源碼分析
Android多線程:HandlerThread使用教程(含實(shí)例講解)
Android多線程:HandlerThread原理及源碼分析
Android多線程:IntentService使用教程(含實(shí)例講解)
Android多線程:IntentService的原理及源碼分析
Android多線程:線程池ThreadPool全方位教學(xué)
相關(guān)使用
Android異步通信:這是一份全面&詳細(xì)的Handler機(jī)制學(xué)習(xí)攻略
Android多線程:手把手教你全面學(xué)習(xí)神秘的Synchronized關(guān)鍵字
Android多線程:帶你了解神秘的線程變量 ThreadLocal
歡迎關(guān)注Carson_Ho的簡書
不定期分享關(guān)于安卓開發(fā)的干貨,追求短盗似、平哩陕、快,但卻不缺深度赫舒。