多线程两种实现方法的区别
Thread类和Runnable接口都可以作为同一功能的方式来实现多线程,但从Java的实际开发角度而言,肯定使用Runnable接口,因为Runnable接口可以有效避免单继承局限。
Thread类的定义:
public class Thread extends Object implements Runnable
- 可以发现Thread类也是Runnable接口的子类。
- 对于Runnable接口和Thread类不太好区分的特点:Thread类和Runnable接口都可实现数据共享,但是Runnable接口可以更加方便地实现数据共享的概念。(此时的数据共享指多个线程访问同一资源的操作)
例1:通过继承Thread类实现卖票程序
package com.yootk.demo;
class MyThread2 extends Thread{ //线程的主体类
private int ticket = 5; //一共5张票
@Override
public void run() { //线程的主方法
for(int x = 0; x < 50; x++){ //循环50次
if(this.ticket > 0){
System.out.println("卖票, ticket = " + this.ticket--);
}
}
}
}
public class MultithreadedImplementation3 {
public static void main(String[] args) {
MyThread2 mt1 = new MyThread2(); //创建线程对象
MyThread2 mt2 = new MyThread2();
MyThread2 mt3 = new MyThread2();
mt1.start(); //启动线程
mt2.start();
mt3.start();
}
}
运行结果:
本程序定义了3个线程对象,希望3个线程对象同时卖5张车票,而最终的结果是一共卖出了15张,等于各卖各自的5张票,此时
不存在数据共享。
例2:利用Runnable接口来实现多线程(实现数据共享)
package com.yootk.demo;
class MyThread3 implements Runnable{
private int ticket = 5;
@Override
public void run() {
for(int x = 0; x < 50; x++){
if(this.ticket > 0){
System.out.println("卖票: ticket = " + this.ticket--);
}
}
}
}
public class MultithreadedImplementation4 {
public static void main(String[] args) {
MyThread3 mt = new MyThread3();
new Thread(mt).start();
new Thread(mt).start();
new Thread(mt).start();
}
}
运行结果:
本程序同时启动了3个线程对象,但是与Thread类操作的买票程序不同的是,这三个线程对象都占着同一个Runnable接口对象的引用(三个线程对象都直接访问同一个数据资源),所以实现了数据共享的操作。