Java多线程两种实现方式的对比

Java多线程两种实现方式的对比
一种,直接继承Thread类
一种,实现Thread类的Runnable接口

两种方式的区别

比如,售票厅有四个窗口,可以发售某日某次列出的100张车票,此时,100张车票可以看作是共享资源,四个售票窗口需要创建四个线程
可以通过Thread的currentThread()方法,得到当前的线程的实例对象,然后,调用getName()方法,可以获取到线程的名称

继承Thread类,实现多线程

示例,Example04.java

public class Example04{
    public static void main(String[] args){
        new TicketWindow().start();     // 创建一个线程对象TicketWindows并开启
        new TicketWindow().start();     // 创建一个线程对象TicketWindows并开启
        new TicketWindow().start();     // 创建一个线程对象TicketWindows并开启
        new TicketWindow().start();     // 创建一个线程对象TicketWindows并开启
    }
}
class TicketWindow extends Thread{
    private int tickets=100;
    public void run(){
        // 通过死循环语句,打印语句
        while(true){
            if (tickets>0){
                // 获取当前线程
                // 获取当前线程的名称
                Thread th=Thread.currentThread();
                String th_name=th.getName();
                System.out.println(th_name+"正在发售第"+tickets--+"张票");
            }
        }
    }

}

编译运行
这里写图片描述
可以看出,每张票都被打印了四次
原因,四个线程没有共享100张票,而是各自出售了100张票
在程序中创建了四个TicketWindow对象,就等于创建了四个售票程序,每个程序中都有100张票,每个线程在独立的处理各自的资源

注意,每个线程都有自己的名字,主线程默认的名字为main,用户创建的第一个线程的默认名字为Thread-0,第二个线程的默认名字为Thread-1,依次类推,如果,希望指定线程的名称,可以通过调用setName(String name)为线程设置名称

由于,现实生活中,系统中的车票资源是共享的,显然上面的运行结果不合理
为了保证资源共享,在程序中只能创建一个售票对象,然后,开启多个线程去运行同一个售票对象的售票方法,简单来说,就是四个线程运行同一个售票程序,此时,就需要用到线程的第二种实现方式

实现Runnable接口,实现多线程

示例,Example05.java

public class Example05{
    public static void main(String[] args){
        TicketWindow tw=new TicketWindow();
        new Thread(tw,"窗口1").start();       // 创建线程对象,并命名为窗口1,开启线程
        new Thread(tw,"窗口2").start();       // 创建线程对象,并命名为窗口2,开启线程
        new Thread(tw,"窗口3").start();       // 创建线程对象,并命名为窗口3,开启线程
        new Thread(tw,"窗口4").start();       // 创建线程对象,并命名为窗口4,开启线程
    }
}
class TicketWindow implements Runnable{
    private int tickets=100;
    public void run(){
        while(true){
            if (tickets>0){
                // 获取当前线程
                // 呼气当前线程的名称
                Thread th=Thread.currentThread();
                String th_name=th.getName();
                System.out.println(th_name+"正在发售第"+tickets--+"张票");
            }
        }
    }
}

编译运行
这里写图片描述
代码说明
只创建了一个TicketWindow对象,然后,创建了四个线程,在每个线程上都去调用TicketWindow对象中的run()方法,这样,就可以保证四个线程访问的是同一个tickets变量,共享100张车票

可以看出,实现Runnable接口,相对于继承Thread类来说

优势如下

1、适合多个相同程序代码的线程,去处理同一个资源的情况,把线程同程序代码、数据有效的分离,很好的体现了面向对象的设计思想

2、可以避免由于Java的单继承,带来的局限性
在程序中,经常遇到这种情况,就是使用一个已经继承了某一个类的子类,创建线程,由于,一个类不能同时有两个父类,所以,不能用继承Thread类的方式,那么,只能采用实现Runnable接口的方式

实际中,大多数应用程序都会采用,实现Runnable接口的方式来创建多线程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值