三种多线程方法的区别
1、直接继承Thread类实现多线程:
//创建子类继承Thread类
class TickWindow extends Thread{
private int tickets = 100;
//重写Thread类中的run方法
public void run(){
while(true){
if(tickets > 0){
System.out.println(Thread.currentThread().getName()+"正在发售第 "+tickets--+" 张票");
}
}
}
}
public class Example04 {
public static void main(String[] args) {
//创建4个线程对象TicketWindow并开启,来模拟4个售票窗口
new TickWindow().start();
new TickWindow().start();
new TickWindow().start();
new TickWindow().start();
}
}
运行结果如下:
可以看出每张票都被发售了4次,和我们平时的售票逻辑是不符合的。出现这种情况的原因是4个线程没有共享这些票,而是每个独自拥有100张票。所以是每个线程独立处理各自的资源,而不是处理共享资源。
2、Runnable接口实现多线程(Callable接口实现也可以):
//定义一个实现Runnable接口的实现类
class TicketWindow2 implements Runnable{
private int tickets = 100;
@Override
public void run() {
while(true){
if(tickets > 0){
System.out.println(Thread.currentThread().getName()+"正在发售第 "+tickets--+" 张票");
}
}
}
}
public class Example05 {
public static void main(String[] args) {
//创建ticketwindow实例对象
TicketWindow2 ticketWindow2 = new TicketWindow2();
new Thread(ticketWindow2,"window 1").start();
new Thread(ticketWindow2,"window 2").start();
new Thread(ticketWindow2,"window 3").start();
new Thread(ticketWindow2,"window 4").start();
}
}
运行结果如下:
在这个例子中,通过Runnable接口的方法只创建了一个TicketWindow2对象,然后创建了4个线程,每个线程都是调用同一个对象的run()方法,这样就确保了4个线程访问的是统一的资源内容,达到共享资源的目的。
优点:
1、适合多个线程处理一个共享资源的情况,将线程如代码、数据有效分离,充分体现了面向对象的设计思想。
2、避免java单继承特性所带来的局限性,因为一个类不能同时继承两个父类,所以在当前的类已经继承了一个父类的前提下,那么就只能采用实现Runnable接口的方法或者Callable接口的方法来实现多线程。