版权声明:本文为博主原创文章,未经博主容许不得转载
源码:github.com/AnliaLee
你们要是看到有错误的地方或者有啥好的建议,欢迎留言评论java
这是Android多线程篇的第一章,咱们就从线程的建立聊起吧。经常使用的线程建立方式有两种(实现Callable接口的方式,咱们放到之后介绍Executor框架的时候再叙)android
咱们本章的主题正是经过比对上述两种方式建立的线程在执行任务时的差异,来理解Thread和Runnable的联系和区别git
先说结论:github
咱们就以经典的卖票系统讲个故事吧。话说有小T(Thread)和小R(Runnable)两个票贩子,手下各有两个业务员,日常就干着倒卖活动门票的活(线程执行任务)。有一天,他们各拿到了5张某演唱会的门票,两人将售票的任务交给手下的业务员多线程
小T这边的业务是这样运转的(定义Thread类的子类,重写run()方法,run()方法即为卖票任务)app
public class TicketThread extends Thread {
private int ticket = 5;
private String name;
public TicketThread(String name) {
this.name = name;
}
public void run() {
for (int i = 0; i < 5; i++) {
if (ticket > 0) {
Log.e("T公司",name + "卖了一张票,编号为t" + (ticket--));
}
}
}
}
复制代码
业务员一大早就开始卖票,很快就卖完了(实例化Thread的子类,调用start()方法启动该线程)框架
TicketThread t1 = new TicketThread("1号业务员");
TicketThread t2 = new TicketThread("2号业务员");
t1.start();
t2.start();
复制代码
而小R的业务流程则是这样的(实现Runnable接口,重写Runnable的run()方法)this
public class TicketRunnable implements Runnable {
private int ticket = 5;
public void run() {
for (int i = 0; i < 5; i++) {
if (ticket > 0) {
Log.e("R公司",Thread.currentThread().getName() + "卖了一张票,编号为r" + (ticket--));
}
}
}
}
复制代码
业务员一样很快就把票卖完了(建立Thread子类的实例,将实现了Runnable接口的对象做为参数实例化Thread对象,调用start()方法启动线程)spa
TicketRunnable runnable = new TicketRunnable();
Thread r1 = new Thread(runnable, "1号业务员");
Thread r2 = new Thread(runnable, "2号业务员");
r1.start();
r2.start();
复制代码
事毕,两人决定吃个饭庆祝一下。一番交流后,小R很惊讶小T为啥能够将一样的票多卖一倍的钱,小T得意地安利了本身的卖票心得:线程
“由于我将票复印了一份,这样我两个小弟就能够各拿一份票去兜售了(经过继承Thread的方式,当新建立一个线程启动时,其绑定的任务一样也新建了一份,这样他们的任务是相互独立的,天然也没法实现资源共享了)”
小R听后感叹不已:
“居然还有这种操做?我耿直地将票交给两个业务员就算了啊(实现Runnable接口的方式,由于都是用同一个Runnable对象建立的线程,所以多线程实际上执行的是同一个任务,这样也就共享了资源)”
接着小R又问小T:“你这么干,过后不怕买到假票的人来找你?” 小T听后不觉得然道:
“怕啥,咱们不都是干完一票就跑路的么(线程执行完run()方法后会自行销毁)”
小R:“我从未见过有如此厚颜无耻之人......”
(未完待续...)
因为小R诚信经营,生意越作越大,但最近他却收到了一些投诉,有顾客说他们买到了假票。小R怀疑是本身手下干的,遂决定招我的监督本身的手下。这天,一个自称synchronized的男人前来应聘...