Runnable接口

前言

  • Android开发中,多线程的使用十分常见
  • 今天,我将全面解析多线程其中一种常见用法:Runnable接口

目录

示意图

1. 简介

示意图

2. 使用讲解

2.1 使用步骤

示意图

特别注意:

  • Java中真正能创建新线程的只有Thread类对象
  • 通过实现Runnable的方式,最终还是通过Thread类对象来创建线程

所以对于 实现了Runnable接口的类,称为 线程辅助类Thread类才是真正的线程类

2.2 具体使用

// 步骤1:创建线程辅助类,实现Runnable接口
 class MyThread implements Runnable{
    ....
    @Override
// 步骤2:复写run(),定义线程行为
    public void run(){
}

}

// 步骤3:创建线程辅助对象,即 实例化 线程辅助类
MyThread mt=new MyThread();

// 步骤4:创建线程对象,即 实例化线程类;线程类 = Thread类;
// 创建时通过Thread类的构造函数传入线程辅助类对象
// 原因:Runnable接口并没有任何对线程的支持,我们必须创建线程类(Thread类)的实例,从Thread类的一个实例内部运行
Thread td=new Thread(mt);

// 步骤5:通过 线程对象 控制线程的状态,如 运行、睡眠、挂起 / 停止
// 当调用start()方法时,线程对象会自动回调线程辅助类对象的run(),从而实现线程操作
td.start();

2.3 简便使用:匿名类

很多情况下,开发者会选择一种更加方便的方法去创建线程:匿名类

    // 步骤1:通过匿名类 直接 创建线程辅助对象,即 实例化 线程辅助类
    Runnable mt = new Runnable() {
                    // 步骤2:复写run(),定义线程行为
                    @Override
                    public void run() {
                    }
                };
            <span class="hljs-comment">// 步骤3:创建线程对象,即 实例化线程类;线程类 = Thread类;</span>
            Thread mt1 = <span class="hljs-keyword">new</span> Thread(mt, <span class="hljs-string">"窗口1"</span>);
       
            <span class="hljs-comment">// 步骤4:通过 线程对象 控制线程的状态,如 运行、睡眠、挂起  / 停止</span>
            mt1.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.demoforrunnable.MainActivity">
//设置一个按钮用以启动线程
<span class="hljs-tag">&lt;<span class="hljs-name">Button</span>
    <span class="hljs-attr">android:id</span>=<span class="hljs-string">"@+id/button"</span>
    <span class="hljs-attr">android:layout_width</span>=<span class="hljs-string">"wrap_content"</span>
    <span class="hljs-attr">android:layout_height</span>=<span class="hljs-string">"wrap_content"</span>
    <span class="hljs-attr">android:text</span>=<span class="hljs-string">"点击开始卖票"</span> /&gt;</span>

</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 {

<span class="hljs-comment">//主布局中定义了一个按钮用以启动线程</span>
Button button;

<span class="hljs-comment">//步骤1:创建线程类,实现Runnable接口</span>
<span class="hljs-keyword">private</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyThread1</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Runnable</span></span>{

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> ticket = <span class="hljs-number">100</span>;<span class="hljs-comment">//一个窗口有100张票</span>

    <span class="hljs-comment">//在run方法里复写需要进行的操作:卖票速度1s/张</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span><span class="hljs-params">()</span></span>{
        <span class="hljs-keyword">while</span> (ticket&gt;<span class="hljs-number">0</span>){
            ticket--;
            System.out.println(Thread.currentThread().getName() + <span class="hljs-string">"卖掉了1张票,剩余票数为:"</span>+ticket);

            <span class="hljs-keyword">try</span> {
                Thread.sleep(<span class="hljs-number">1000</span>);<span class="hljs-comment">//卖票速度是1s一张</span>
            } <span class="hljs-keyword">catch</span> (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span><span class="hljs-params">(Bundle savedInstanceState)</span> </span>{
    <span class="hljs-keyword">super</span>.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    <span class="hljs-comment">//Button按下时会开启一个新线程执行卖票</span>
    button = (Button) findViewById(R.id.button);
    button.setOnClickListener(<span class="hljs-keyword">new</span> View.OnClickListener() {
        <span class="hljs-meta">@Override</span>
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onClick</span><span class="hljs-params">(View v)</span> </span>{

            <span class="hljs-comment">//步骤2:创建线程类的实例</span>
            <span class="hljs-comment">//创建二个线程,模拟二个窗口卖票</span>
            MyThread1 mt1 = <span class="hljs-keyword">new</span> MyThread1();
            MyThread1 mt2 = <span class="hljs-keyword">new</span> MyThread1();

            Thread mt11 = <span class="hljs-keyword">new</span> Thread(mt1, <span class="hljs-string">"窗口1"</span>);
            Thread mt22 = <span class="hljs-keyword">new</span> Thread(mt2, <span class="hljs-string">"窗口2"</span>);

            <span class="hljs-comment">//步骤3:调用start()方法开启线程</span>
            <span class="hljs-comment">//启动二个线程,也即是窗口,开始卖票</span>
            mt11.start();
            mt22.start();
        }
    });
}

}

  • 测试结果
示意图

实例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.demoforrunnable2.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.demoforrunnable2;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

<span class="hljs-comment">//主布局中定义了一个按钮用以启动线程</span>
Button button;

<span class="hljs-comment">//步骤1:创建线程类,实现Runnable接口</span>
<span class="hljs-comment">//由于需要实现两个不同的操作:卖票速度1s/张和3s/张</span>
<span class="hljs-comment">//所以需要创建两个线程类并实现Runnable接口</span>

<span class="hljs-comment">//第一个线程类:实现卖票速度1s/张操作</span>
<span class="hljs-keyword">private</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyThread1</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Runnable</span></span>{

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> ticket = <span class="hljs-number">100</span>;<span class="hljs-comment">//一个窗口有100张票</span>

    <span class="hljs-comment">//在run方法里复写需要进行的操作:卖票速度1s/张</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span><span class="hljs-params">()</span></span>{
        <span class="hljs-keyword">while</span> (ticket&gt;<span class="hljs-number">0</span>){
            ticket--;
            System.out.println(Thread.currentThread().getName() + <span class="hljs-string">"卖掉了1张票,剩余票数为:"</span>+ticket);

            <span class="hljs-keyword">try</span> {
                Thread.sleep(<span class="hljs-number">1000</span>);<span class="hljs-comment">//卖票速度是1s一张</span>
            } <span class="hljs-keyword">catch</span> (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

<span class="hljs-comment">//第二个线程类:实现卖票速度3s/张操作</span>
<span class="hljs-keyword">private</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyThread2</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Runnable</span></span>{

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> ticket = <span class="hljs-number">100</span>;<span class="hljs-comment">//一个窗口有100张票</span>

    <span class="hljs-comment">//在run方法里复写需要进行的操作:卖票速度3s/张</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span><span class="hljs-params">()</span></span>{
        <span class="hljs-keyword">while</span> (ticket&gt;<span class="hljs-number">0</span>){
            ticket--;
            System.out.println(Thread.currentThread().getName() + <span class="hljs-string">"卖掉了1张票,剩余票数为:"</span>+ticket);

            <span class="hljs-keyword">try</span> {
                Thread.sleep(<span class="hljs-number">3000</span>);<span class="hljs-comment">//卖票速度是3s一张</span>
            } <span class="hljs-keyword">catch</span> (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span><span class="hljs-params">(Bundle savedInstanceState)</span> </span>{
    <span class="hljs-keyword">super</span>.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    <span class="hljs-comment">//Button按下时会开启一个新线程执行卖票</span>
    button = (Button) findViewById(R.id.button);
    button.setOnClickListener(<span class="hljs-keyword">new</span> View.OnClickListener() {
        <span class="hljs-meta">@Override</span>
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onClick</span><span class="hljs-params">(View v)</span> </span>{

            <span class="hljs-comment">//步骤2:创建线程类的实例</span>
            <span class="hljs-comment">//分别实例化两个线程子类</span>
            MyThread1 mt1 = <span class="hljs-keyword">new</span> MyThread1();
            MyThread2 mt2 = <span class="hljs-keyword">new</span> MyThread2();

            <span class="hljs-comment">//创建二个线程,模拟二个窗口卖票</span>
            Thread mt11 = <span class="hljs-keyword">new</span> Thread(mt1, <span class="hljs-string">"窗口1"</span>);<span class="hljs-comment">//卖票速度1s/张</span>
            Thread mt22 = <span class="hljs-keyword">new</span> Thread(mt2, <span class="hljs-string">"窗口2"</span>);<span class="hljs-comment">//卖票速度3s/张</span>

            <span class="hljs-comment">//步骤3:调用start()方法开启线程</span>
            <span class="hljs-comment">//启动二个线程,也即是窗口,开始卖票</span>
            mt11.start();
            mt22.start();

        }
    });
}

}

  • 测试结果
    由于卖票速度不同,所以窗口1卖3张时,窗口2才卖1张。


    示意图

实例3

  • 应用场景:创建两个线程-实现一个耗时任务
  • 实例说明:实现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.demoforrunnable3.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.demoforrunnable3;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

<span class="hljs-comment">//主布局中定义了一个按钮用以启动线程</span>
Button button;

<span class="hljs-comment">//步骤1:创建线程类,实现Runnable接口</span>
<span class="hljs-keyword">private</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyThread1</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Runnable</span></span>{

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> ticket = <span class="hljs-number">100</span>;<span class="hljs-comment">//两个窗口一共要卖100张票</span>

    <span class="hljs-comment">//在run方法里复写需要进行的操作:卖票速度1s/张</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span><span class="hljs-params">()</span></span>{
        <span class="hljs-keyword">while</span> (ticket&gt;<span class="hljs-number">0</span>){
            ticket--;
            System.out.println(Thread.currentThread().getName() + <span class="hljs-string">"卖掉了1张票,剩余票数为:"</span>+ticket);

            <span class="hljs-keyword">try</span> {
                Thread.sleep(<span class="hljs-number">1000</span>);<span class="hljs-comment">//卖票速度是1s一张</span>
            } <span class="hljs-keyword">catch</span> (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span><span class="hljs-params">(Bundle savedInstanceState)</span> </span>{
    <span class="hljs-keyword">super</span>.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    <span class="hljs-comment">//Button按下时会开启一个新线程执行卖票</span>
    button = (Button) findViewById(R.id.button);
    button.setOnClickListener(<span class="hljs-keyword">new</span> View.OnClickListener() {
        <span class="hljs-meta">@Override</span>
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onClick</span><span class="hljs-params">(View v)</span> </span>{

            <span class="hljs-comment">//步骤2:创建线程类的实例</span>
            <span class="hljs-comment">//因为是两个窗口共卖100张票,即共用资源</span>
            <span class="hljs-comment">//所以只实例化一个实现了Runnable接口的类</span>
            MyThread1 mt = <span class="hljs-keyword">new</span> MyThread1();

            <span class="hljs-comment">//因为要创建二个线程,模拟二个窗口卖票</span>
            Thread mt11 = <span class="hljs-keyword">new</span> Thread(mt, <span class="hljs-string">"窗口1"</span>);
            Thread mt12 = <span class="hljs-keyword">new</span> Thread(mt, <span class="hljs-string">"窗口2"</span>);

            <span class="hljs-comment">//步骤3:调用start()方法开启线程</span>
            <span class="hljs-comment">//启动二个线程,也即是窗口,开始卖票</span>
            mt11.start();
            mt12.start();

        }
    });
}

}


4. 与 “继承Thread类”对比

  • Java中,继承 Thread类和实现Runnable接口是实现多线程最常用的2种方法
  • 今天我们就来对比下这两种方法

若还不熟悉 继承Thread类的使用,请看文章Android多线程:继承Thread类 使用解析(含实例教程)

示意图

5. 总结

  • 本文主要对多线程中实现 Runnable的用法进行了全面介绍
  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值