zoukankan      html  css  js  c++  java
  • 关于多线程两种方法的思考 卖票问题 同步代码块加锁问题

    package com.swift.duoxiancheng;
    
    class Ticket extends Thread {
        Ticket(String name) {
            super(name); // 构造函数:设置线程名称
        }
    
        public static int ticket = 1000;
    
        @Override
        public void run() {
    
            while (true) {
                synchronized ("锁") {
                    if (ticket > 0) {
                        ticket--;
                        System.out.println(Thread.currentThread().getName() + "还有余票数:" + ticket);
                    }
                }
            }
        }
    
        public synchronized void sellTickets() {
    
        }
    }
    
    public class ThreadTest_Jicheng {
        public static void main(String[] args) {
            // 一種是多個線程對應一個對象(如賣票),一種是多個線程對應多個對象(如socket線程)
            Ticket t1 = new Ticket("賣票窗口1");
            Ticket t2 = new Ticket("賣票窗口2");
            Ticket t3 = new Ticket("賣票窗口3");
            Ticket t4 = new Ticket("賣票窗口4");
            // 上面這種賣票是生成4個對象,每個對象有1000張票要賣出,只是因為線程得到CPU分配有先有后
            // 用靜態成員變量共享1000張票,票不在對象的對空間,而在內存方法區,同步問題要解決
    
            t1.start();
            t2.start();
            t3.start();
            t4.start();
            System.out.println("Hello World!");
        }
    }

    上面是继承Thread的方法

    这种方法较为简单,只要继承后复写run方法即可,缺点是已经继承别的类就不能在继承了,有局限性。对单一对象中成员进行操作的多线程需要静态static关键字

    下面是实现implements Runnable方法

    package com.swift.duoxiancheng;
    
    class Tickets implements Runnable {
    
        private int ticket = 1000;
    
        @Override
        public void run() {
            sell();
        }
    
        // 给带循环的方法加synchronized之后只有一个线程卖票,是因为锁定一个线程执行循环当然只有一个线程在卖票,应该把锁加在循环里边
        // 加在里边仍然有线程等待在循环外,最后出现负票数的情况,因为while之外也出现了同步,方法中不循环卖票,只卖一张票
        // while中写判断会影响结果,出现负票数
        public void sell() {
            while (true) {
                synchronized (this) {
                    if (ticket > 0) {
                        try {
                            Thread.sleep(0);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        ticket--;
                        System.out.println(Thread.currentThread().getName() + "還有餘票:" + ticket);
                    }
                }
            }
        }
    }
    
    public class SellTickets_Runnable {
        public static void main(String[] args) {
            Tickets t = new Tickets();
    
            Thread t1 = new Thread(t, "票窗口1");
            Thread t2 = new Thread(t, "票窗口2");
            Thread t3 = new Thread(t, "票窗口3");
            Thread t4 = new Thread(t, "票窗口4");
    
            t1.start();
            t2.start();
            t3.start();
            t4.start();
            System.out.println("Hello World!");
        }
    }

    锁可以在方法上,也可以用同步代码块,同步代码块较好,可以局部锁

    锁可以使对象synchronized(this) 也可以是字符串synchronized("锁")

    加锁的时候注意,如果锁住的是一个循环,那就只有一个线程执行直到完成

    package com.swift.duoxiancheng;
    
    class Ticketz implements Runnable {
    
        private int ticket = 100;
    
        @Override
        public void run() {
            sell();
    
        }
        //加上synchronized之后只有一个线程卖票,锁定一个线程执行循环当然只有一个线程在卖票
        public synchronized void sell() {
            while (ticket > 0) {
                try {
                    Thread.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                ticket--;
                System.out.println(Thread.currentThread().getName() + "還有餘票:" + ticket);
            }
        }
    }
    
    public class SellTickets_OnlyOneThreadSell {
        public static void main(String[] args) {
            Ticketz t = new Ticketz();
    
            Thread t1 = new Thread(t, "票窗口1");
            Thread t2 = new Thread(t, "票窗口2");
            Thread t3 = new Thread(t, "票窗口3");
            Thread t4 = new Thread(t, "票窗口4");
    
            t1.start();
            t2.start();
            t3.start();
            t4.start();
            System.out.println("Hello World!");
        }
    }
  • 相关阅读:
    笔试题 易错题目解析
    SqlServer 函数 大全
    视频上传到自己的服务器打不开
    sql 计算生日提请日期
    Web API 异常处理(转)
    微软源代码管理工具TFS2013安装与使用详细图文教程(Vs2013)
    关于枚举的用法和类型转换
    html title换行方法 如a链接标签内title属性鼠标悬停提示内容换行
    JS的parent、opener、self对象
    uploadfiy
  • 原文地址:https://www.cnblogs.com/qingyundian/p/8277625.html
Copyright © 2011-2022 走看看