Android初学之Runnable和Thread
2016-07-27 15:12
543 查看
Runnable代表了一条能被执行的命令,经常用在不同的线程里去执行一段代码的接口。其中只有一个方法:void run(),该方法用于执行相关的业务代码,当实现了Runnable接口的类创建了一个线程并启动了该线程(即使用了void start()方法)时,会调用run方法。
Runnable的使用:
1、 实现Runables接口外部类:
很容易能够看出上述代码的缺点:MyThread中的方法只是用了一次,但是却以一个外部类的形式描述,显然是不合理的,因此可以在匿名内部类表述出来。匿名内部类一般用于只执行一次的情况下使用,减少代码量,而外部类主要适用于需要多次重复使用的情况。
2、匿名内部类
3、Runnable的一些理解:
我们暂且抛开匿名内部类和外部类的区别,看一下上述代码的输出结果发现,两个线程的输出是交替出现的,且两个线程id是不同的。
所以,我们就好理解为什么API中说它是运行在一个不同的线程里了。
4、 如果直接调用Runnable的run方法会出现什么情况呢?
运行的输出结果如下:
因为次数只有10次,为保证正确性,我实验了n次,发现都是上述结果。
上图中,线程id是一样的,也就是说根本没有新开一个线程去运行Runnable相关的代码,而是直接在主线程运行的,说明了一点:直接调用run方法,不经过start并不能实现多线程,也就是像Runnable源码中解释的那样,Runnable只是一个代表了一条能被执行的命令,经常用在不同的线程里去执行一段代码的接口,注意它是用在线程里,而不是自身就能直接多线程。
我们再看看Thread中的start方法:
start方法完成了实现多线程的初始化操作,run方法中完成了业务操作(一般是编程者自己写的业务实现代码)。至于如何实现的,则不是我们需要关心的。
Thread是一个执行并发的单元,他有自己的方法调用栈,参数栈和本地变量的栈。每一个应用开始后,在主线程组中至少有一个运行着的主线程。Thread本质上来说他是一个实现了Runnable接口的类,他在Runnable的基础上添加了一些能够保证多线程运行的机制。一般来说有两种方法在新线程中执行业务代码:
1、继承了Thread并重写了run方法的Thread子类。
2、将一个实现了Runnable接口的实例作为Thread的构造参数(Runnable中的demo就是这么做的)。
除了大量的构造函数,还有一些基本成员属性,比如name、priority、stackSize、packState等,这些属性都是为了更好的实现多线程。
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等,这些属性都是为了更好的实现多线程。
相关文章推荐
- java-模拟tomcat服务器
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件