一、基本概念
Android中的多线程主要是为了操作一些耗时的工作,防止其将主程序进行阻塞,与Java一样两种方式:1、继承Thread 2、实现Runnable接。但是Android与Java的多线程有一点区别是Android中的更新UI必须在主线程中进行,否则抛出异常,因为Android的UI是线程不安全的。
1、Thread类
Android中的Thread类是扩展了java.lang.Thread类的多线程类,其中有一个构造函数其实也实现了Runnable的接口,源码如下:
/**
* Constructs a new {@code Thread} with a {@code Runnable} object, the given
* name and belonging to the {@code ThreadGroup} passed as parameter.
*
* @param group
* {@code ThreadGroup} to which the new {@code Thread} will
* belong
* @param runnable
* a {@code Runnable} whose method <code>run</code> will be
* executed by the new {@code Thread}
* @param threadName
* the name for the {@code Thread} being created
* @param stackSize
* a stack size for the new {@code Thread}. This has a highly
* platform-dependent interpretation. It may even be ignored
* completely.
* @throws IllegalThreadStateException
* if <code>group.destroy()</code> has already been done
* @see java.lang.ThreadGroup
* @see java.lang.Runnable
*/
public Thread(ThreadGroup group, Runnable runnable, String threadName, long stackSize) {
if (threadName == null) {
throw new NullPointerException("threadName == null");
}
create(group, runnable, threadName, stackSize);
}
Thread类代表线程类,它的两个最主要的方法是:
run()——包含线程运行时所执行的代码
Start()——用于启动线程
2、Runnable接口
public interface Runnable {
/**
* Starts executing the active part of the class' code. This method is
* called when a thread is started that has been created with a class which
* implements {@code Runnable}.
*/
void run();
}
Runable源码如上所示,可以看到中只有run方法。下面的例子中的Runable在主线程执行修改UI的代码,并且“OK”的执行是在输出10个“runable”后,所以分析得到Runable只是一个接口并没有开启线程,依旧是运行在UI线程中。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
runnable.run();
Log.d("RunnableTest", "OK");
}
Runnable runnable = new Runnable() {
@Override
public void run() {
for(int i = 0;i<10;i++) {
textView.setText("runable");
Log.d("RunnableTest", "runable");
}
}
};
二、Thread与Runnable实现多线程方法对比
以网上多线程学习最经典的买票系统为例:
1、Thread实现
public class TicketThread extends Thread{
private int ticket = 10;
public void run(){
for(int i =0;i<10;i++){
synchronized (this){
if(this.ticket>0){
try {
Thread.sleep(100);
System.out.println(Thread.currentThread().getName()+"卖票---->"+(this.ticket--));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public static void main(String[] arg){
TicketThread t1 = new TicketThread();
new Thread(t1,"线程1").start();
new Thread(t1,"线程2").start();
}
}
输出:
线程1卖票—->10
线程1卖票—->9
线程1卖票—->8
线程2卖票—->7
线程2卖票—->6
线程1卖票—->5
线程1卖票—->4
线程2卖票—->3
线程2卖票—->2
线程1卖票—->1
2、Runnable实现
public class TicketRunnable implements Runnable{
private int ticket = 10;
@Override
public void run() {
for(int i =0;i<10;i++){
//添加同步快
synchronized (this){
if(this.ticket>0){
try {
//通过睡眠线程来模拟出最后一张票的抢票场景
Thread.sleep(100);
System.out.println(Thread.currentThread().getName()+"卖票---->"+(this.ticket--));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
public static void main(String[] arg){
TicketRunnable t1 = new TicketRunnable();
new Thread(t1, "线程1").start();
new Thread(t1, "线程2").start();
}
}
输出:
线程1卖票—->10
线程1卖票—->9
线程1卖票—->8
线程1卖票—->7
线程2卖票—->6
线程2卖票—->5
线程2卖票—->4
线程2卖票—->3
线程2卖票—->2
线程2卖票—->1
三、总结
从上面的例子可以看出两种方式均可实现多线程也都可以实现资源共享,区别最主要的就是一个是继承,一个是实现。
实现Runnable接口比继承Thread类所具有的优势总结如下:
1):适合多个相同的程序代码的线程去处理同一个资源,把虚拟CPU(线程)同程序的代码,数据有效的分离,较好地体现了面向对象的设计思想。
2):可以避免java中的单继承的限制,比如当我们要将已经继承了某一个类的子类放入多线程中,由于一个类不能同时有两个父类,所以不能用继承Thread类的方式,那么,这个类就只能采用实现Runnable接口的方式了
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。当多个线程的执行代码来自同一个类的实例时,即称它们共享相同的代码。多个线程操作相同的数据,与它们的代码无关。当共享访问相同的对象是,即它们共享相同的数据。当线程被构造时,需要的代码和数据通过一个对象作为构造函数实参传递进去,这个对象就是一个实现了Runnable接口的类的实例。
本文介绍了Android中实现多线程的两种方式:继承Thread和实现Runnable接口。尽管两者都能实现多线程,但Runnable更利于资源共享和避免单继承限制。通过卖票系统的示例,展示了两种方式在实际应用中的表现。

1183

被折叠的 条评论
为什么被折叠?



