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

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)+"票");
    }
}

上一篇:【树】FBI树


下一篇:P1087 FBI树