多线程的创建
对于多线程的实现,有两种方式,一种是通过继承Thread类来实现,一种是通过实现Runnable接口来实现多线程。
下面我将举个栗子来说明两者的具体实现
关于多个窗口卖票的问题
1.继承Thread类
1.创建一个继承Thread类的子类
2.重写run()方法
3.创建其子类对象
4.通过此对对象调用start()方法
class Window extends Thread {
private static int tickets = 100;
@Override
public void run() {
while (true) {
if (tickets > 0) {
System.out.println (getName () + "卖票,票号为: " + tickets );
tickets--;
} else {
break;
}
}
}
}
public class Mythread {
public static void main(String[] args) {
Window t1 = new Window ();
Window t2 = new Window ();
Window t3 = new Window ();
t1.setName ( "窗口1" );
t2.setName ( "窗口2" );
t3.setName ( "窗口3" );
t1.start ();
t2.start ();
t3.start ();
}
}
创建了三组对象,默认创建的实例不共享,我们本意是共卖出100张票,在没有加入static之前,三个窗口卖300张票,给变量加上static关键字后,此变量变为全局变量。从而实现多线程(这里没有讨论线程安全问题。
那么想要实现数据共享呢,我们可以引入Runnable 接口通过实现接口中的run()方法来实现多线程。
2.实现Runnable接口方法
1.实现了Runnable接口的类
2.实现类去实现Runnable中的抽象方法run(),因为Runnable是接口,只有run()方法,没有start()方法,也就是说只是实现Runnable接口是无法启动现线程的,必须要借助其他类
3.创建实现类的对象,而Thread类中有一个构造方法,参数是Runnable对象,也就是说可以通过Thread类来启动Runnable实现的多线程。
4.将此对象作为参数传递给Thread类的构造器中,创建Thread类的对象
5.通过Thread类的对象调用start()方法来启动线程
class MThread implements Runnable {
private int tickets = 100;
@Override
public void run() {
while (true) {
if (tickets > 0) {
System.out.println (Thread.currentThread ().getName () + "卖票,票号为: " + tickets );
tickets--;
} else {
break;
}
}
}
}
public class MtThread {
public static void main(String[] args) {
MThread mThread = new MThread ();
Thread t1 = new Thread ( mThread );
Thread t2 = new Thread ( mThread );
Thread t3 = new Thread ( mThread );
t1.start ();
t2.start ();
t3.start ();
}
}
我们知道关于start()方法,有两种作用,一种是启动线程,另一种是调用当前线程的run()方法,那么为什么我们能保证实现的是Runnable接口中的run()方法???
我们来看一下JDK的Thread源码
private Runnable target;
public void run() {
if (target != null) {
target.run();
}
}
在run()方法中,首先会检查target是否为空,如果不是,则执行该target的run()方法。
两种方法的联系与区别
通常我们在java开发中会选择第二种方法,一是因为继承具有局限性,第二种方法没有类的单继承性的局限性
而是因为方法二实现了数据共享,而方法一默认数据不共享。