Thread -- 04 -- Thread和Runnable的区别

原文链接:Thread – 04 – Thread和Runnable的区别


相关文章:


在日常开发过程中,除了使用线程池来创建线程外,我们还可以通过继承 Thread 类或者实现 Runnable 接口来创建线程,那么它们之间又有什么区别呢,这里让我们来一起深入了解下


一、举例说明

  • 例子一 (继承 Thread 类)

    public class MyThread extends Thread {
    
        private String name;
        private int ticket = 5;
    
        public MyThread(String name) {
            this.name = name;
        }
    
        @Override
        public void run() {
            do {
                System.out.println("总共【" + ticket-- + "】张票," 
                    + this.name+ "卖出一张票,还剩【" + ticket + "】张票");
            } while (ticket >= 1);
        }
    }
    
    public class ThreadDemo {
    
        public static void main(String[] args) {
            new MyThread("一号窗口").start();
            new MyThread("二号窗口").start();
            new MyThread("三号窗口").start();
        }
    }
    
    // 总共【5】张票,一号窗口卖出一张票,还剩【4】张票
    // 总共【5】张票,三号窗口卖出一张票,还剩【4】张票
    // 总共【5】张票,二号窗口卖出一张票,还剩【4】张票
    // 总共【4】张票,三号窗口卖出一张票,还剩【3】张票
    // 总共【4】张票,一号窗口卖出一张票,还剩【3】张票
    // 总共【3】张票,一号窗口卖出一张票,还剩【2】张票
    // 总共【3】张票,三号窗口卖出一张票,还剩【2】张票
    // 总共【4】张票,二号窗口卖出一张票,还剩【3】张票
    // 总共【2】张票,三号窗口卖出一张票,还剩【1】张票
    // 总共【2】张票,一号窗口卖出一张票,还剩【1】张票
    // 总共【1】张票,三号窗口卖出一张票,还剩【0】张票
    // 总共【3】张票,二号窗口卖出一张票,还剩【2】张票
    // 总共【1】张票,一号窗口卖出一张票,还剩【0】张票
    // 总共【2】张票,二号窗口卖出一张票,还剩【1】张票
    // 总共【1】张票,二号窗口卖出一张票,还剩【0】张票
    
    • 如上所示,我们定义了一个 MyThread 类使其继承 Thread 类,在 main() 方法中,我们 new 了三个 MyThread 类并调用其 start() 方法

    • 由输出可知,三个窗口各自卖出了 5 张票,即总共卖出了 15 张票


  • 例子二 (实现 Runnable 接口)

    public class MyRunnable implements Runnable {
    
        private int ticket = 5;
        private boolean isOk = true;
    
        @Override
        public synchronized void run() {
            do {
                if (!isOk) {
                    this.notifyAll();
                }
                System.out.println("总共【" + ticket-- + "】张票," 
                    + Thread.currentThread().getName() + "卖出一张票,还剩【" + ticket + "】张票");
                try {
                    isOk = false;
                    if (ticket == 0) {
                        break;
                    }
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } while (ticket >= 1);
        }
    }
    
    public class RunnableDemo {
    
        public static void main(String[] args) {
            MyRunnable mr = new MyRunnable();
            new Thread(mr, "一号窗口").start();
            new Thread(mr, "二号窗口").start();
            new Thread(mr, "三号窗口").start();
        }
    }
    
     // 总共【5】张票,一号窗口卖出一张票,还剩【4】张票
     // 总共【4】张票,三号窗口卖出一张票,还剩【3】张票
     // 总共【3】张票,二号窗口卖出一张票,还剩【2】张票
     // 总共【2】张票,三号窗口卖出一张票,还剩【1】张票
     // 总共【1】张票,一号窗口卖出一张票,还剩【0】张票
    
    • 如上所示,我们定义了一个 MyRunnable 类使其实现了 Runnable 接口,在 main() 方法中,我们 new 了一个 MyRunnable 类,并将其作为参数传入到 new 的三个线程当中

    • 由输出可知,三个窗口一共卖了 5 张票


二、结果分析

  • 例子一中,三个线程 (窗口) 分别使用其各自的资源,也就是说分别给三个线程 (窗口) 5 张票去进行处理,各自完成各自的任务

    • 由于 Thread 类本生实现了 Runnable 接口,因此也可以跟例子二一样,创建三个线程并传入同一个 MyThread,从而实现资源共享
  • 例子二中,三个线程 (窗口) 共享了一个资源,也就是说总共 5 张票给三个线程 (窗口) 去进行处理,共同完成任务

    • 由于三个线程共享一个资源,会存在线程安全的问题,因此使用了 synchronized 来对 run() 方法进行加锁,从而保证线程安全

三、归纳总结

  • Thread 类实现了 Runnable 接口,使得 run() 方法支持多线程

  • Thread 是类,Runnable 是接口

  • 由于类的单一继承原则,推荐使用 Runnable 接口

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值