美文网首页
线程同步的三个例子

线程同步的三个例子

作者: 何几时 | 来源:发表于2020-11-29 23:22 被阅读0次

    synchronized 用法有两种,简单区分:

    1. synchronized 函数 -- 程序只有一个类,把实际操作的函数从 run()方法 独立出来,在该函数定义前面加一个 synchronized 关键字(private synchronized void buy()
    2. synchronized 代码块 -- 程序有两个类以上,把实际要操作的变量所在对象找到
    synchronized (account){
                // 判断有没有钱
          if (drawingMoney > account.money) {
              System.out.println(Thread.currentThread().getName()+"钱不够了,取不了");
              return;
          }
    
          try {
              Thread.sleep(1000);
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
    
           // 卡内余额
          account.money = account.money - drawingMoney;
          nowMoney = nowMoney + drawingMoney;
          System.out.println(account.name+"余额为:"+account.money);
    //    System.out.println(Thread.currentThread().getName());
          System.out.println(this.getName()+"手里的钱"+nowMoney);
    }
    

    三个例子

    1.抢票程序(线程不安全版)

    package demo04_synchronized;
    
    
    // 不安全地买票
    // 线程不安全,有负数
    // WARNING!!
    // 每个线程在自己的工作内存交互,内存控制不当会造成数据不一致
    public class UnsafeBuyTicket {
        public static void main(String[] args) {
            BuyTicket station = new BuyTicket();
    
            new Thread(station, "苦逼的我们").start();
            new Thread(station, "牛逼的你们").start();
            new Thread(station, "可恶的黄牛党").start();
        }
    
    }
    
    class BuyTicket implements Runnable{
    
        // 票
        private int ticketNums = 10;
        boolean flag = true; // 外部停止方式
    
    
        @Override
        public void run() {
            // 买票
            while (flag){
                buy();
            }
        }
    
        private void buy(){
            // 判断是否有票
            if (ticketNums <= 0) {
                flag = false;
                return;
            }
    
            // 延时设置
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            // 买票
            System.out.println(Thread.currentThread().getName()+
                    "买到第"+ticketNums--+"张票");
        }
    
    }
    
    

    抢票程序改进版

    只是在 buy() 函数前加了个 synchronized

    package demo04_synchronized;
    
    
    // 不安全地买票
    // 线程不安全,有负数
    // WARNING!!
    // 每个线程在自己的工作内存交互,内存控制不当会造成数据不一致
    public class UnsafeBuyTicket {
        public static void main(String[] args) {
            BuyTicket station = new BuyTicket();
    
            new Thread(station, "苦逼的我们").start();
            new Thread(station, "牛逼的你们").start();
            new Thread(station, "可恶的黄牛党").start();
        }
    
    }
    
    class BuyTicket implements Runnable{
    
        // 票
        private int ticketNums = 10;
        boolean flag = true; // 外部停止方式
    
    
        @Override
        public void run() {
            // 买票
            while (flag){
                buy();
            }
        }
    
        private synchronized void buy(){
            // 判断是否有票
            if (ticketNums <= 0) {
                flag = false;
                return;
            }
    
            // 延时设置
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            // 买票
            System.out.println(Thread.currentThread().getName()+
                    "买到第"+ticketNums--+"张票");
        }
    
    }
    

    2.银行取钱例子(线程不安全版)

    package demo04_synchronized;
    
    
    // 不安全的取钱
    // 两个人去银行取钱,账户
    public class UnsafeBank {
        public static void main(String[] args) {
            Account account = new Account(100, "结婚基金");
            Drawing you = new Drawing(account, 50, "you");
            Drawing gf = new Drawing(account, 100, "gf");
    
            you.start();
            gf.start();
    
        }
    }
    
    // 账户
    class Account{
        int money;  // 余额
        String name; // 卡名
    
        public Account(int money, String name) {
            this.money = money;
            this.name = name;
        }
    }
    
    
    // 银行:模拟取款
    class Drawing extends Thread{
        Account account; // 账户
        // 取了多少钱
        int drawingMoney;
        // 手里余额
        int nowMoney;
    
        public Drawing(Account account, int drawingMoney, String name){
            super(name);
            this.account = account;
            this.drawingMoney = drawingMoney;
        }
    
        // 取钱
        // synchronized 默认锁的是 this
        @Override
        public void run() {
            // 判断有没有钱
            if (drawingMoney > account.money) {
                System.out.println(Thread.currentThread().getName()+"钱不够了,取不了");
                return;
            }
    
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            // 卡内余额
            account.money = account.money - drawingMoney;
            nowMoney = nowMoney + drawingMoney;
            System.out.println(account.name+"余额为:"+account.money);
    //        System.out.println(Thread.currentThread().getName());
            System.out.println(this.getName()+"手里的钱"+nowMoney);
    
        }
    }
    

    改进版(线程安全版)

    package demo04_synchronized;
    
    
    // 不安全的取钱
    // 两个人去银行取钱,账户
    public class UnsafeBank {
        public static void main(String[] args) {
            Account account = new Account(100, "结婚基金");
            Drawing you = new Drawing(account, 50, "you");
            Drawing gf = new Drawing(account, 100, "gf");
    
            you.start();
            gf.start();
    
        }
    }
    
    // 账户
    class Account{
        int money;  // 余额
        String name; // 卡名
    
        public Account(int money, String name) {
            this.money = money;
            this.name = name;
        }
    }
    
    
    // 银行:模拟取款
    class Drawing extends Thread{
        Account account; // 账户
        // 取了多少钱
        int drawingMoney;
        // 手里余额
        int nowMoney;
    
        public Drawing(Account account, int drawingMoney, String name){
            super(name);
            this.account = account;
            this.drawingMoney = drawingMoney;
        }
    
        // 取钱
        // synchronized 默认锁的是 this
        @Override
        public void run() {
    
            // 要判断锁住要操作的对象是谁?就是要增删改查的变量在哪,这里是account,而不是this
            synchronized (account){
                // 判断有没有钱
                if (drawingMoney > account.money) {
                    System.out.println(Thread.currentThread().getName()+"钱不够了,取不了");
                    return;
                }
    
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
                // 卡内余额
                account.money = account.money - drawingMoney;
                nowMoney = nowMoney + drawingMoney;
                System.out.println(account.name+"余额为:"+account.money);
    //        System.out.println(Thread.currentThread().getName());
                System.out.println(this.getName()+"手里的钱"+nowMoney);
    
            }
            }
    }
    

    3.线程入队列例子(线程不安全版)

    package demo04_synchronized;
    
    
    import java.util.ArrayList;
    import java.util.List;
    
    // 线程不安全的集合
    public class UnsafeList {
        public static void main(String[] args) {
            List<String> list= new ArrayList<String>();
            for (int i = 0; i < 10000; i++) {
                new Thread(()->{
                    list.add(Thread.currentThread().getName());
                }).start();
            }
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(list.size());
        }
    }
    

    改进版(线程安全版)

    package demo04_synchronized;
    
    
    import java.util.ArrayList;
    import java.util.List;
    
    // 线程不安全的集合
    public class UnsafeList {
        public static void main(String[] args) {
            List<String> list= new ArrayList<String>();
            for (int i = 0; i < 10000; i++) {
    
                synchronized (list) {
                    new Thread(()->{
                        list.add(Thread.currentThread().getName());
                    }).start();
                }
            }
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(list.size());
        }
    }
    

    相关文章

      网友评论

          本文标题:线程同步的三个例子

          本文链接:https://www.haomeiwen.com/subject/tfplwktx.html