zoukankan      html  css  js  c++  java
  • Runnable的作用及使用方式

    前言

    Java中实现多线程主要由以下两种方式:继承Thread类和实现Runnable接口,本文主要说明Runnable接口实现多线程。

    Runnable接口简介

    (1)定义
    Runnable接口是线程辅助类,仅定义了一个方法run()方法
    (2)作用
    实现多线程
    (3)优点
    灵活:Runnable可以继承其他类实现对Runnable实现类的增强,避免了Thread类由于继承Thread类而无法继承其他类的问题
    共享资源:Runnable接口的run()方法可以被多个线程共享,适用于多个进程处理一种资源的问题

    使用方法

    (1) 实现Runnable接口
    (2) 重写run()方法
    (3) 创建runnable实例
    (4) 创建Thread实例
    (5) 将Runnable实例放入Thread实例中
    (6) 通过线程实例控制线程的行为(运行,停止),在运行时会调用Runnable接口中的run方法。

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

    Runnable方式也分为标准方式和匿名方式
    (1)标准方式

    public class MainActivity extends AppCompatActivity {
        Button btn;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            btn = findViewById(R.id.btn);
            //2.创建MyRunnable实例
            MyRunnable runnable=new MyRunnable();
            //3.创建Thread对象
            //4.将MyRunnable放入Thread实例中
            Thread thread=new Thread(runnable);
            //5.通过线程对象操作线程(运行、停止)
            thread.start();
    
        }
        //1.实现runnable接口并重写run方法
        class MyRunnable implements Runnable{
    
            @Override
            public void run() {
    
            }
        }
    }
    

    (2)匿名方式

    public class MainActivity extends AppCompatActivity {
        Button btn;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            //1.匿名实现Runnable接口并重写run方法
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
    
                }
            };
            //2.创建线程对象
            //3.将runnable实例放入线程对象中
            Thread thread=new Thread(runnable);
            //4.由线程实例控制线程的行为(运行,停止)
            thread.start();
    
        }
    
    }
    

    实际用例

    现在假设有两个窗口卖车票,每一秒卖出一张车票,每个窗口有100张票
    activity_main.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.zhqy.threaddemo.MainActivity">
    
        <Button
            android:id="@+id/btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            android:text="售票"
            />
    
    </android.support.constraint.ConstraintLayout>
    

    MainActivity.java:

    package com.zhqy.threaddemo;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    
    public class MainActivity extends AppCompatActivity {
        Button btn;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            btn=findViewById(R.id.btn);
            btn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //创建runnnable实例
                    TicketRunnable run1=new TicketRunnable();
                    TicketRunnable run2=new TicketRunnable();
                    //创建Thread实例并将runnable实例放入
                    Thread th1=new Thread(run1,"th1");
                    Thread th2=new Thread(run2,"th2");
                    //通过线程实例控制线程的行为(运行、停止)
                    th1.start();
                    th2.start();
                }
            });
        }
         //实现Runnable接口并重写run方法
        class TicketRunnable implements  Runnable{
            int ticket=100;
            @Override
            public void run() {
                //卖票
                while (ticket>0){
                    Log.e(Thread.currentThread().getName(),"剩余票量:"+(--ticket));
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
    }
    

    测试结果:

    08-26 10:52:21.954 10088-10241/com.zhqy.threaddemo E/th1: 剩余票量:99
    08-26 10:52:21.954 10088-10242/com.zhqy.threaddemo E/th2: 剩余票量:99
    08-26 10:52:22.955 10088-10242/com.zhqy.threaddemo E/th2: 剩余票量:98
    08-26 10:52:22.955 10088-10241/com.zhqy.threaddemo E/th1: 剩余票量:98
    08-26 10:52:23.955 10088-10241/com.zhqy.threaddemo E/th1: 剩余票量:97
    08-26 10:52:23.955 10088-10242/com.zhqy.threaddemo E/th2: 剩余票量:97
    08-26 10:52:24.956 10088-10241/com.zhqy.threaddemo E/th1: 剩余票量:96
    08-26 10:52:24.956 10088-10242/com.zhqy.threaddemo E/th2: 剩余票量:96
    08-26 10:52:25.956 10088-10242/com.zhqy.threaddemo E/th2: 剩余票量:95
    08-26 10:52:25.956 10088-10241/com.zhqy.threaddemo E/th1: 剩余票量:95
    08-26 10:52:26.957 10088-10241/com.zhqy.threaddemo E/th1: 剩余票量:94
    08-26 10:52:26.957 10088-10242/com.zhqy.threaddemo E/th2: 剩余票量:94
    08-26 10:52:27.958 10088-10241/com.zhqy.threaddemo E/th1: 剩余票量:93
    08-26 10:52:27.958 10088-10242/com.zhqy.threaddemo E/th2: 剩余票量:93
    08-26 10:52:28.958 10088-10241/com.zhqy.threaddemo E/th1: 剩余票量:92
    08-26 10:52:28.958 10088-10242/com.zhqy.threaddemo E/th2: 剩余票量:92
    

    那么如何让两个窗口共享“车票”呢?

    package com.zhqy.threaddemo;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    
    public class MainActivity extends AppCompatActivity {
        Button btn;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            btn=findViewById(R.id.btn);
            btn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //创建runnnable实例
                    TicketRunnable run1=new TicketRunnable();
    
                    //创建Thread实例并将runnable实例放入
                    Thread th1=new Thread(run1,"th1");
                    Thread th2=new Thread(run1,"th2");
                    //通过线程实例控制线程的行为(运行、停止)
                    th1.start();
                    th2.start();
                }
            });
        }
         //实现Runnable接口并重写run方法
        class TicketRunnable implements  Runnable{
            int ticket=100;
            @Override
            public void run() {
                //卖票
                while (ticket>0){
                    Log.e(Thread.currentThread().getName(),"剩余票量:"+(--ticket));
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
    }
    

    这里看出两个线程公用了一个Runnable实现对象实例,这样两个线程就可以操作同一个共享资源--“车票”
    测试结果

    08-26 10:58:10.681 11641-11675/com.zhqy.threaddemo E/th2: 剩余票量:98
    08-26 10:58:10.681 11641-11674/com.zhqy.threaddemo E/th1: 剩余票量:99
    08-26 10:58:11.681 11641-11675/com.zhqy.threaddemo E/th2: 剩余票量:97
    08-26 10:58:11.682 11641-11674/com.zhqy.threaddemo E/th1: 剩余票量:96
    08-26 10:58:12.682 11641-11675/com.zhqy.threaddemo E/th2: 剩余票量:95
    08-26 10:58:12.683 11641-11674/com.zhqy.threaddemo E/th1: 剩余票量:94
    08-26 10:58:13.683 11641-11675/com.zhqy.threaddemo E/th2: 剩余票量:93
    08-26 10:58:13.684 11641-11674/com.zhqy.threaddemo E/th1: 剩余票量:92
    08-26 10:58:14.683 11641-11675/com.zhqy.threaddemo E/th2: 剩余票量:91
    08-26 10:58:14.684 11641-11674/com.zhqy.threaddemo E/th1: 剩余票量:90
    08-26 10:58:15.684 11641-11675/com.zhqy.threaddemo E/th2: 剩余票量:89
    08-26 10:58:15.685 11641-11674/com.zhqy.threaddemo E/th1: 剩余票量:88
    08-26 10:58:16.685 11641-11675/com.zhqy.threaddemo E/th2: 剩余票量:87
    08-26 10:58:16.685 11641-11674/com.zhqy.threaddemo E/th1: 剩余票量:86
    08-26 10:58:17.686 11641-11675/com.zhqy.threaddemo E/th2: 剩余票量:85
    08-26 10:58:17.686 11641-11674/com.zhqy.threaddemo E/th1: 剩余票量:84
    

    需要注意的是--线程同步问题

    Thread与Runnable方式的对比

     
    对比图.png

    两种方式推荐使用实现Runnbale接口的方法,如果只想重写run方法也推荐使用实现Runnable接口的方式。

    以上就是实现Runnbale接口实现多线程的全部内容。

  • 相关阅读:
    最大子数组问题
    剑指offer python版 树的子结构
    剑指offer python版 重建二叉树
    剑指offer python版 字符串变成整数
    剑指offer python版 构建乘积数组
    剑指offer python版 不用加减乘除做加法
    剑指offer python版 求1+2+…+n
    剑指offer python版 股票最大收益
    剑指offer python版 圆圈中最后剩下的数字
    剑指offer python版 扑克牌的顺子
  • 原文地址:https://www.cnblogs.com/Proximacentaurus/p/13635711.html
Copyright © 2011-2022 走看看