Android初学之Runnable和Thread

来源:互联网 发布:对网络直播的看法作文 编辑:程序博客网 时间:2024/06/07 12:33

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等,这些属性都是为了更好的实现多线程。

0 0
原创粉丝点击