← 返回首页
JavaSE基础教程(一百零八)
发表时间:2023-03-24 16:59:20
线程池案例

线程池案例

题目:

兵马俑景区每天限流10000名游客参观,现有A,B,C三个售票窗口,使用多线程模拟三个售票窗口的售票过程,并统计每个窗口各买了多少张门票。

1.设计门票类

public class Ticket {
    public static int TICKET_NUM=10000; //每天限流10000人
}

2.设计售票窗口类

public class SaleWindow {

    private Ticket ticket;

    public SaleWindow(Ticket ticket){
        this.ticket = ticket;
    }
    public int windowsASaleNumber=0;
    public int windowsBSaleNumber=0;
    public int windowsCSaleNumber=0;

}

1.1 使用传统的Runnable接口实现

public class TicketDemoWithRunnable implements Runnable {

    private final SaleWindow saleWindow;

    public TicketDemoWithRunnable(SaleWindow saleWindow){
        this.saleWindow = saleWindow;
    }

    @Override
    public void run() {
        while (true){
            synchronized (saleWindow){
                if(Ticket.TICKET_NUM<=0){
                    System.out.println("今天的门票全部售完!!");
                    break;
                }

                Ticket.TICKET_NUM--;
                if( "窗口A".equals(Thread.currentThread().getName())){
                    System.out.println("A窗口售出一张票,还剩:" + Ticket.TICKET_NUM+"张门票...");
                    saleWindow.windowsASaleNumber++;
                }
                if( "窗口B".equals(Thread.currentThread().getName())){
                    System.out.println("B窗口售出一张票,还剩:" + Ticket.TICKET_NUM+"张门票...");
                    saleWindow.windowsBSaleNumber++;
                }
                if( "窗口C".equals(Thread.currentThread().getName())){
                    System.out.println("C窗口售出一张票,还剩:" + Ticket.TICKET_NUM+"张门票...");
                    saleWindow.windowsCSaleNumber++;
                }
            }
        }
    }


    public static void main(String[] args) {
        Ticket ticket = new Ticket();
        SaleWindow saleWindow = new SaleWindow(ticket);
        TicketDemoWithRunnable ticketDemoWithRunnable = new TicketDemoWithRunnable(saleWindow);
        Thread windowAThread = new Thread(ticketDemoWithRunnable,"窗口A");
        Thread windowBThread = new Thread(ticketDemoWithRunnable,"窗口B");
        Thread windowCThread = new Thread(ticketDemoWithRunnable,"窗口C");

        windowAThread.start();
        windowBThread.start();
        windowCThread.start();

        try{
            windowAThread.join();
            windowBThread.join();
            windowCThread.join();
        }catch (Exception ex){
            ex.printStackTrace();
        }
        System.out.println("A窗口卖了:"+saleWindow.windowsASaleNumber+"张票");
        System.out.println("B窗口卖了:"+saleWindow.windowsBSaleNumber+"张票");
        System.out.println("C窗口卖了:"+saleWindow.windowsCSaleNumber+"张票");
    }
}

1.2 使用线程池实现

import java.util.concurrent.*;
class SaleWindowRunnable implements Runnable {

    private final SaleWindow saleWindow;

    public SaleWindowRunnable(SaleWindow saleWindow) {
        this.saleWindow = saleWindow;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (saleWindow) {
                if (Ticket.TICKET_NUM <= 0) {
                    System.out.println("今天的门票全部售完!!");
                    break;
                }

                Ticket.TICKET_NUM--;
                if ("窗口A".equals(Thread.currentThread().getName())) {
                    System.out.println("A窗口售出一张票,还剩:" + Ticket.TICKET_NUM + "张门票...");
                    saleWindow.windowsASaleNumber++;
                }
                if ("窗口B".equals(Thread.currentThread().getName())) {
                    System.out.println("B窗口售出一张票,还剩:" + Ticket.TICKET_NUM + "张门票...");
                    saleWindow.windowsBSaleNumber++;
                }
                if ("窗口C".equals(Thread.currentThread().getName())) {
                    System.out.println("C窗口售出一张票,还剩:" + Ticket.TICKET_NUM + "张门票...");
                    saleWindow.windowsCSaleNumber++;
                }
            }
        }
    }
}

public class TicketDemoWithPool {

    //阻塞式关闭线程池。
    public static void awaitAfterShutdown(ExecutorService threadPool) {
        threadPool.shutdown();
        try {
            if (!threadPool.awaitTermination(200, TimeUnit.SECONDS)) {
                threadPool.shutdownNow();
            }
        } catch (InterruptedException ex) {
            threadPool.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }

    public static void main(String[] args) {

        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(3, 10, 3,
                TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(3), new ThreadFactory() {
            final String[] profix = {"A", "B", "C"};
            int index = 0; //计数器.... //第一个线程就是:'小张',第二个就是'小李',以此类推.....
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r, "窗口" + profix[index++]);
            }
        }, new ThreadPoolExecutor.DiscardOldestPolicy());


        Ticket ticket = new Ticket();
        SaleWindow saleWindow = new SaleWindow(ticket);

        SaleWindowRunnable saleWindowRunnable = new SaleWindowRunnable(saleWindow);
        threadPool.submit(saleWindowRunnable);
        threadPool.submit(saleWindowRunnable);
        threadPool.submit(saleWindowRunnable);

        awaitAfterShutdown(threadPool);

        System.out.println("A窗口卖了:"+saleWindow.windowsASaleNumber+"张票");
        System.out.println("B窗口卖了:"+saleWindow.windowsBSaleNumber+"张票");
        System.out.println("C窗口卖了:"+saleWindow.windowsCSaleNumber+"张票");
    }

}

运行结果:

...
A窗口卖了:3547张票
B窗口卖了:2993张票
C窗口卖了:3460张票