Android初学之Runnable和Thread

Runnable代表了一条能被执行的命令,经常用在不同的线程里去执行一段代码的接口。其中只有一个方法:void run(),该方法用于执行相关的业务代码,当实现了Runnable接口的类创建了一个线程并启动了该线程(即使用了void start()方法)时,会调用run方法。


Runnable的使用:

1、 实现Runables接口外部类:

public class MainActivity extends AppCompatActivity {


    public class MyThread implements Runnable{

        @Override
        public void run() {
            for(int i=0;i<10;i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("这是一个实现了Runnable的线程");
            }
        }
    }
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    protected void onResume() {
        super.onResume();
        MyThread myThread = new MyThread();
//        Thread thread = new Thread(myThread);
//        thread.start();
        myThread.run();
        for(int i=0;i<10;i++){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("这是主线程");
        }
    }
}

很容易能够看出上述代码的缺点:MyThread中的方法只是用了一次,但是却以一个外部类的形式描述,显然是不合理的,因此可以在匿名内部类表述出来。匿名内部类一般用于只执行一次的情况下使用,减少代码量,而外部类主要适用于需要多次重复使用的情况。


2、匿名内部类

ackage com.zhouyou.robocademoproj;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    protected void onResume() {
        super.onResume();
       Runnable runnable = new Runnable() {
           @Override
           public void run() {
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               for(int i=0;i<8;i++){
                   System.out.println("这是匿名内部类的使用");
               }
           }
       };
        Thread thread = new Thread(runnable);
        thread.start();

        for(int i = 0;i<8;i++){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("这是主线程的使用");
        }
    }
}

3、Runnable的一些理解:
我们暂且抛开匿名内部类和外部类的区别,看一下上述代码的输出结果发现,两个线程的输出是交替出现的,且两个线程id是不同的。
这里写图片描述
所以,我们就好理解为什么API中说它是运行在一个不同的线程里了。


4、 如果直接调用Runnable的run方法会出现什么情况呢?

package com.zhouyou.robocademoproj;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    protected void onResume() {
        super.onResume();
       Runnable runnable = new Runnable() {
           @Override
           public void run() {
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               for(int i=0;i<8;i++){
                   System.out.println("这是匿名内部类的使用");
               }
           }
       };
        runnable.run();
        //直接调用run方法,不使用Thread的start
//        Thread thread = new Thread(runnable);
//        thread.start();

        for(int i = 0;i<8;i++){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("这是主线程的使用");
        }
    }
}

运行的输出结果如下:
这里写图片描述
因为次数只有10次,为保证正确性,我实验了n次,发现都是上述结果。
上图中,线程id是一样的,也就是说根本没有新开一个线程去运行Runnable相关的代码,而是直接在主线程运行的,说明了一点:直接调用run方法,不经过start并不能实现多线程,也就是像Runnable源码中解释的那样,Runnable只是一个代表了一条能被执行的命令,经常用在不同的线程里去执行一段代码的接口,注意它是用在线程里,而不是自身就能直接多线程。
我们再看看Thread中的start方法:

    /**
     * Starts the new Thread of execution. The <code>run()</code> method of
     * the receiver will be called by the receiver Thread itself (and not the
     * Thread calling <code>start()</code>).
     *
     * @throws IllegalThreadStateException - if this thread has already started.
     * @see Thread#run
     */
    public synchronized void start() {
        checkNotStarted();

        hasBeenStarted = true;

        nativeCreate(this, stackSize, daemon);
    }

start方法完成了实现多线程的初始化操作,run方法中完成了业务操作(一般是编程者自己写的业务实现代码)。至于如何实现的,则不是我们需要关心的。


Thread是一个执行并发的单元,他有自己的方法调用栈,参数栈和本地变量的栈。每一个应用开始后,在主线程组中至少有一个运行着的主线程。Thread本质上来说他是一个实现了Runnable接口的类,他在Runnable的基础上添加了一些能够保证多线程运行的机制。一般来说有两种方法在新线程中执行业务代码:

1、继承了Thread并重写了run方法的Thread子类。
2、将一个实现了Runnable接口的实例作为Thread的构造参数(Runnable中的demo就是这么做的)。

除了大量的构造函数,还有一些基本成员属性,比如name、priority、stackSize、packState等,这些属性都是为了更好的实现多线程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值