ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

多线程---使用synchronized---多窗口出售火车票

2021-12-31 23:32:41  阅读:162  来源: 互联网

标签:count Thread 多窗口 --- flag new Ticket 多线程 public


package com.ldp.demo.Thread;

public class Ticket_Synchronized {
    public static void main(String[] args) {
        Ticket_tation ticket = new Ticket_tation();
        new Thread(ticket, "a") {
        }.start();
        new Thread(ticket, "b") {
        }.start();
        new Thread(ticket, "c") {
        }.start();
        new Thread(ticket, "d") {
        }.start();
    }

}
class Ticket_tation implements Runnable {
    private int ticketNum = 10;

    @Override
    public void run() {
        while (ticketNum > 0) {   //while和synchronized 的位置不能互换,
            synchronized (this) { //要不然票会一直是同一个窗口出票
                                   //synchronized 在这里锁的是对象
              
                if (ticketNum==0){
                    System.out.println( Thread.currentThread().getName()+"出票失败,"+"票已售完!" );
                    return;
                }
                try {
                    Thread.sleep(50);//睡眠50毫秒,要不然执行太快,会是同一个窗口出票
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println((ticketNum--) + "号票已售出!" + Thread.currentThread().getName());
            }
        }

    }

}

结果

10号票已售出!a
9号票已售出!d
8号票已售出!d
7号票已售出!c
6号票已售出!b
5号票已售出!b
4号票已售出!c
3号票已售出!c
2号票已售出!c
1号票已售出!d
a出票失败,票已售完!
c出票失败,票已售完!
b出票失败,票已售完!

这种方式效率太低,因为synchronized(this)锁住的是对象,代码块里所有的内容都被阻塞了,耗费时间,可以改为锁具体操作,即锁扣除票数方法substract_ticket();

package com.ldp.demo.Thread;

public class Ticket_Synchronized {
    public static void main(String[] args) {
        Ticket_tation ticket = new Ticket_tation();
        new Thread(ticket, "a") {
        }.start();
        new Thread(ticket, "b") {
        }.start();
        new Thread(ticket, "c") {
        }.start();
        new Thread(ticket, "d") {
        }.start();
    }

}

class Ticket_tation implements Runnable {
    private int ticketNum = 3;

    public synchronized Result substract_ticket() {
        if (ticketNum == 0) {
            return new Result(false, ticketNum);
        }
        return new Result(true, ticketNum--);
    }

    @Override
    public void run() {
        while (ticketNum > 0) {
            if (ticketNum == 0) {
                System.out.println(Thread.currentThread().getName() + "出票失败," + "票已售完!");
                return;
            }
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Result result = substract_ticket();
            if (!result.isFlag()) {
                System.out.println(Thread.currentThread().getName() + "出票失败," + "票已售完!");
                return;
            }
            System.out.println(result.getCount() + "号票已售出!" + Thread.currentThread().getName());
        }

    }

}


class Result {
    boolean flag;
    int count;

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public Result() {
    }

    public Result(boolean flag, int count) {
        this.flag = flag;
        this.count = count;
    }
}

3号票已售出!a
2号票已售出!d
b出票失败,票已售完!
1号票已售出!c
a出票失败,票已售完!

synchronized锁的是非静态方法也叫对象锁。

多个线程调用同一个对象的同步方法会阻塞,调用不同对象的同步方法不会阻塞。(java对象的内存地址是否相同)

synchronized修饰静态的方法也叫类锁

1,要满足方法同步(或者代码块同步)就必须保证多线程访问的是同一个对象(在java内存中的地址是否相同)。

2,类锁和对象锁同时存在时,多线程访问时不会阻塞,因为他们不是一个锁。

假如有两个火车站,每个火车站有两个窗口售票,那就不能锁对象了,要锁具体操作的方法了。

package com.ldp.demo.Thread;

import org.apache.commons.lang3.time.StopWatch;

/**
 * 多个火车站多个窗口售票
 */
public class ThreadTicket {
    private static final int NUM = 7;

    public static int getNum() {
        return NUM;
    }

    public static void main(String[] args) {
        Ticket.getTicket().setTicketNum(NUM);

        TicketStation station1 = new TicketStation("南火车站");
        TicketStation station2 = new TicketStation("西火车站");

        new Thread(station1, "西窗口一").start();
        new Thread(station2, "南窗口二").start();
        new Thread(station2, "西窗口一").start();
        new Thread(station1, "南窗口二").start();


    }
}

class Ticket {
    private static final Ticket ticket = new Ticket();

    public Ticket() {
    }

    public static Ticket getTicket() {
        return ticket;
    }

    private int TicketNum;

    public int getTicketNum() {
        return TicketNum;
    }

    public void setTicketNum(int ticketNum) {
        this.TicketNum = ticketNum;
    }

    public synchronized Result substratTicket() {
        Result result = new Result();
        if (TicketNum == 0) {
            result.setFlag(false);
            result.setCount(TicketNum);
        } else {
            result.setFlag(true);
            result.setCount(TicketNum);
            --TicketNum;
        }


        return result;
    }

}

class TicketStation implements Runnable {
    private String name;

    public String getName() {
        return name;
    }

    public TicketStation() {
    }

    public TicketStation(String name) {
        this.name = name;
    }

    @Override
    public void run() {


        while (Ticket.getTicket().getTicketNum() > 0) {
            if (Ticket.getTicket().getTicketNum() == 0) {
                break;
            }
            try {
                Thread.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Result result = Ticket.getTicket().substratTicket();

            if (result.isFlag()) {
                Out.getInstance().write(System.currentTimeMillis(), this, Thread.currentThread().getName(), result.getCount());
            } else {
                System.out.println(System.currentTimeMillis() + this.name + Thread.currentThread().getName() + "出票失败");
            }

        }

    }
}

class Result {
    boolean flag;
    int count;

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public Result() {
    }

    public Result(boolean flag, int count) {
        this.flag = flag;
        this.count = count;
    }
}
package com.ldp.demo.Thread;

class Out{
    private final static Out out=new Out();
    private Out(){}
    public static Out getInstance(){
        return out;
    }
    static void write(long time,TicketStation station,String adress,int count){

        System.out.println(time+
                station.getName()+"在"+adress+"卖出了第"+(ThreadTicket.getNum()-count+1)+"票");
    }
}

标签:count,Thread,多窗口,---,flag,new,Ticket,多线程,public
来源: https://blog.csdn.net/qq_35327989/article/details/122262956

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有