zoukankan      html  css  js  c++  java
  • 【线程实现的两种方式及区别】

    我们来用最经典的卖票的案例,表明两种实现方式的区别,同时分析线程不安全产生的原因

    一、继承Thread类

    package test;
    
    /**
     * @Description
     * @Author shusheng
     * @Email shusheng@yiji.com
     * @Date 2018/8/31
     */
    public class SellTicketOne extends Thread{
    
        private static int tickets = 100;
    
        @Override
        public void run(){
            while(true){
                if(tickets>0){
                    System.out.println(getName()+"正在出售第"+tickets+"张票");
                    tickets--;
                }
            }
        }
    
    }

    二、实现Runnable接口

    package test;
    
    /**
     * @Description
     * @Author shusheng
     * @Email shusheng@yiji.com
     * @Date 2018/8/31
     */
    public class SellTicketTwo implements Runnable{
    
        private static int tickets = 100;
    
        @Override
        public void run(){
            while(true){
                if(tickets>0){
                    System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
                    tickets--;
                }
            }
        }
    
    }

    启动线程

    package test;
    
    /**
     * @Description
     * @Author shusheng
     * @Email shusheng@yiji.com
     * @Date 2018/8/31
     */
    public class SellTicketTest {
    
        public static void main(String[] args) {
    
            SellTicketOne one1 = new SellTicketOne();
            SellTicketOne one2 = new SellTicketOne();
            SellTicketOne one3 = new SellTicketOne();
            one1.setName("窗口一");
            one2.setName("窗口二");
            one3.setName("窗口三");
            one1.start();
            one2.start();
            one3.start();
    
            SellTicketTwo two = new SellTicketTwo();
            Thread t1 = new Thread(two,"窗口四");
            Thread t2 = new Thread(two,"窗口五");
            Thread t3 = new Thread(two,"窗口六");
            t1.start();
            t2.start();
            t3.start();
    
        }
    }

    可以看到,二者的主要区别是:

    1.实现Runnable接口的方式可以避免由于JAVA单继承带来局限性

    2.实现Runnable接口的方式,适用多个相同程序的代码去处理同一个资源的情况,把线程同程序的代码、数据有效分离,较好的体现了面向对象的设计思想。

    加上每次卖票延迟200毫秒,运行程序,发现两个问题:

    A:相同的票卖了多次:CPU的一次操作必须是原子性

    B:出现了负数票:随机性和延迟导致的

    终身学习者
  • 相关阅读:
    第1章:路线图
    第0章:战胜恐惧和懊悔
    c++ 变量 定义 声明
    两个无符号数相减 可以得到负数
    c++ cast operator(类型转换操作符)
    C++中static 的使用方式,以及与c中的static的区别
    重载overload 重写override 重定义redefining
    用到位运算的题目
    C++ 虚函数表解析
    虚函数 动态绑定 实现方式是:虚函数表
  • 原文地址:https://www.cnblogs.com/zuixinxian/p/9565888.html
Copyright © 2011-2022 走看看