JAVA多线程之Thread VS Runnable
2015-10-28 17:55
483 查看
1,在java中开发线程主要有两种方式,一种是继承自Thread类,另一种是实现Runnable接口。
2,线程创建的两种方式:
a,继承Thread类:
class MyThread eatends Thread{
......
@Override
public void run(){
}
}
MyThread mt=new MyThread();
mt.start();
b,实现Runnable接口:
class MyThread implements Runnable{
......
@Override
public void run(){
}
}
MyThread mt=new MyThread();
Thread th=new Thread(mt);
td.start();
说明:在继承Thread类的main方法中,只需创建线程(MyThread mt=new MyThread()),
然后开启线程(mt.start())即可,但在实现Runnable接口的main方法中,还要向线程
(Thread th=new Thread(mt))中传递一个参数mt,mt为线程类(MyThread)实例化
的一个对象。
3,两种创建方式的比较:
a,Runnable方式可以避免Thread方式由于java单继承带来的缺陷,就是每次只能继承一个Thread。
b,Runnable的代码可以被多个线程(Runnable实例)共享,适合多个线程处理同一资源的情况。
4,关于这两种方式的区别,很难说明白,下面我用售票系统的代码来分析:
场景描述:假设春节来临,广州到北京的火车票还有5张,现在通过3个售票窗口来出售,这三个
售票窗口同时开放,随机的出售车票
代码实现:
a,首先通过继承Thread创建线程,来完成这项工作,然后分析结果,代码如下:
class MyThread extends Thread{
//一共有五张车票
private int TicketsCount=5;
//窗口,也就是线程的名字
private String name;
public MyThread(String name){
this.name=name;
}
@Override
public void run() {
while (TicketsCount>0) {
TicketsCount--;
System.out.println(name+"卖了一张票,剩余票数为:"+TicketsCount);
}
}
}
public class TicketsThread {
public static void main(String[] args) {
//创建三个线程,模拟三个售票窗口
MyThread mt1=new MyThread("窗口1");
MyThread mt2=new MyThread("窗口2");
MyThread mt3=new MyThread("窗口3");
//启动三个线程,开始卖票
mt1.start();
mt2.start();
mt3.start();
}
}
执行结果:
窗口1卖了一张票,剩余票数为:4
窗口2卖了一张票,剩余票数为:4
窗口1卖了一张票,剩余票数为:3
窗口2卖了一张票,剩余票数为:3
窗口1卖了一张票,剩余票数为:2
窗口2卖了一张票,剩余票数为:2
窗口1卖了一张票,剩余票数为:1
窗口2卖了一张票,剩余票数为:1
窗口3卖了一张票,剩余票数为:4
窗口3卖了一张票,剩余票数为:3
窗口1卖了一张票,剩余票数为:0
窗口3卖了一张票,剩余票数为:2
窗口3卖了一张票,剩余票数为:1
窗口3卖了一张票,剩余票数为:0
窗口2卖了一张票,剩余票数为:0
嗯?总共有5张票,现在3个售票窗口怎么卖出了15张票?仔细观察我们会发现,其实每个售票窗口
都卖出了5张票。这是怎么回事?其实这是java单继承所带来的缺陷,在创建线程时,3个窗口各自
创建了一个线程,每个线程都有自己的TicketsCount和name,各自执行了自己的run方法,所以在执
行程序时每个售票窗口都卖出了5张票。
b,通过实现Runnable接口的方法,来完成这项工作,代码如下:
class MyThread2 implements Runnable{
private int TicketsCount=5;
@Override
public void run() {
while (TicketsCount>0) {
TicketsCount--;
System.out.println(Thread.currentThread().getName()+"卖出了一张票,剩余票数为:
"+TicketsCount);
}
}
}
public class TicketsRunnable{
public static void main(String[] args) {
//实例化对象
MyThread2 mt=new MyThread2();
//创建三个线程,模拟三个售票窗口
Thread th1=new Thread(mt,"窗口1");
Thread th2=new Thread(mt,"窗口2");
Thread th3=new Thread(mt,"窗口3");
//启动三个线程,开始卖票
th1.start();
th2.start();
th3.start();
}
}
执行结果:
窗口1卖出了一张票,剩余票数为:4
窗口2卖出了一张票,剩余票数为:2
窗口2卖出了一张票,剩余票数为:0
窗口3卖出了一张票,剩余票数为:3
窗口1卖出了一张票,剩余票数为:1
我们会发现,通过实现Runnable接口的方法所得到的结果正是我们想要的。MyThread2是实现
Runnable接口的,先通过类实例化出对象(mt),然后再把对象作为参数传递给3个线程对象,
也就是说3个线程对象传递的是同一个Runnable对象,从而实现了资源(TicketsCount=5)共
享,所以三个售票窗口总共卖出了5张票。
通过这个例子,我们已经清楚了Runnable和Thread 的区别。还需要强调一点,无论是继承
Thread类,还是实现Runnable方法,都需要重写run()方法,然后在run()方法了实现要做的事
情,最后通过start()方法启动线程。
2,线程创建的两种方式:
a,继承Thread类:
class MyThread eatends Thread{
......
@Override
public void run(){
}
}
MyThread mt=new MyThread();
mt.start();
b,实现Runnable接口:
class MyThread implements Runnable{
......
@Override
public void run(){
}
}
MyThread mt=new MyThread();
Thread th=new Thread(mt);
td.start();
说明:在继承Thread类的main方法中,只需创建线程(MyThread mt=new MyThread()),
然后开启线程(mt.start())即可,但在实现Runnable接口的main方法中,还要向线程
(Thread th=new Thread(mt))中传递一个参数mt,mt为线程类(MyThread)实例化
的一个对象。
3,两种创建方式的比较:
a,Runnable方式可以避免Thread方式由于java单继承带来的缺陷,就是每次只能继承一个Thread。
b,Runnable的代码可以被多个线程(Runnable实例)共享,适合多个线程处理同一资源的情况。
4,关于这两种方式的区别,很难说明白,下面我用售票系统的代码来分析:
场景描述:假设春节来临,广州到北京的火车票还有5张,现在通过3个售票窗口来出售,这三个
售票窗口同时开放,随机的出售车票
代码实现:
a,首先通过继承Thread创建线程,来完成这项工作,然后分析结果,代码如下:
class MyThread extends Thread{
//一共有五张车票
private int TicketsCount=5;
//窗口,也就是线程的名字
private String name;
public MyThread(String name){
this.name=name;
}
@Override
public void run() {
while (TicketsCount>0) {
TicketsCount--;
System.out.println(name+"卖了一张票,剩余票数为:"+TicketsCount);
}
}
}
public class TicketsThread {
public static void main(String[] args) {
//创建三个线程,模拟三个售票窗口
MyThread mt1=new MyThread("窗口1");
MyThread mt2=new MyThread("窗口2");
MyThread mt3=new MyThread("窗口3");
//启动三个线程,开始卖票
mt1.start();
mt2.start();
mt3.start();
}
}
执行结果:
窗口1卖了一张票,剩余票数为:4
窗口2卖了一张票,剩余票数为:4
窗口1卖了一张票,剩余票数为:3
窗口2卖了一张票,剩余票数为:3
窗口1卖了一张票,剩余票数为:2
窗口2卖了一张票,剩余票数为:2
窗口1卖了一张票,剩余票数为:1
窗口2卖了一张票,剩余票数为:1
窗口3卖了一张票,剩余票数为:4
窗口3卖了一张票,剩余票数为:3
窗口1卖了一张票,剩余票数为:0
窗口3卖了一张票,剩余票数为:2
窗口3卖了一张票,剩余票数为:1
窗口3卖了一张票,剩余票数为:0
窗口2卖了一张票,剩余票数为:0
嗯?总共有5张票,现在3个售票窗口怎么卖出了15张票?仔细观察我们会发现,其实每个售票窗口
都卖出了5张票。这是怎么回事?其实这是java单继承所带来的缺陷,在创建线程时,3个窗口各自
创建了一个线程,每个线程都有自己的TicketsCount和name,各自执行了自己的run方法,所以在执
行程序时每个售票窗口都卖出了5张票。
b,通过实现Runnable接口的方法,来完成这项工作,代码如下:
class MyThread2 implements Runnable{
private int TicketsCount=5;
@Override
public void run() {
while (TicketsCount>0) {
TicketsCount--;
System.out.println(Thread.currentThread().getName()+"卖出了一张票,剩余票数为:
"+TicketsCount);
}
}
}
public class TicketsRunnable{
public static void main(String[] args) {
//实例化对象
MyThread2 mt=new MyThread2();
//创建三个线程,模拟三个售票窗口
Thread th1=new Thread(mt,"窗口1");
Thread th2=new Thread(mt,"窗口2");
Thread th3=new Thread(mt,"窗口3");
//启动三个线程,开始卖票
th1.start();
th2.start();
th3.start();
}
}
执行结果:
窗口1卖出了一张票,剩余票数为:4
窗口2卖出了一张票,剩余票数为:2
窗口2卖出了一张票,剩余票数为:0
窗口3卖出了一张票,剩余票数为:3
窗口1卖出了一张票,剩余票数为:1
我们会发现,通过实现Runnable接口的方法所得到的结果正是我们想要的。MyThread2是实现
Runnable接口的,先通过类实例化出对象(mt),然后再把对象作为参数传递给3个线程对象,
也就是说3个线程对象传递的是同一个Runnable对象,从而实现了资源(TicketsCount=5)共
享,所以三个售票窗口总共卖出了5张票。
通过这个例子,我们已经清楚了Runnable和Thread 的区别。还需要强调一点,无论是继承
Thread类,还是实现Runnable方法,都需要重写run()方法,然后在run()方法了实现要做的事
情,最后通过start()方法启动线程。
相关文章推荐
- 我对java集合框架一无所知①(2015年10月28日)
- Spring整合mongo-client示例
- Java:IO流与IO设备
- java反射--Field
- Java栈的模拟实现
- J2EE框架(Struts&Hibernate&Spring)的理解
- Sending e-mail with Spring MVC--转载
- 我理解中的简单工厂模式
- JAVA----关键字用法
- Java NIO系列教程(二) Channel
- Java:IO流之字符流缓冲区详解
- Eclipse项目导入到Android studio中
- Spring-Bean的生命周期
- Java中如何遍历Map对象的4种方法
- 美图2016校招java编程
- java 接口回调
- java Vamei快速教程19 嵌套类
- Java解析eml内容和附件
- Java:IO流之字符流Reader、Writer详解
- Spring MVC 中的 forward 和 redirect