Java的多线程同步方法

如何设计 航空公司某航班共有120张机票,模拟4个窗口同时进行该航班的售票工作。

上锁!


public class Aviation implements Runnable{

    private int tickets = 120;

    @Override
    public void run() {
        while (true) {
            synchronized (this) {
                if (tickets <= 0) {
                    break;
                }
                System.out.println(Thread.currentThread().getName() + "售出一张票,剩余:" + (--tickets) + "张票");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        Aviation aviation = new Aviation();
        for (int i = 1; i <= 4; i++) {
            new Thread(aviation, "窗口" + i).start();
        }
    }
}

多线程实现代码如下:

public class Answer7724336 {

    public static void main(String[] args) {
        int windows = 4;
        ExecutorService es = Executors.newFixedThreadPool(windows);
        for(int i=0; i<windows; ++i) {
            es.submit(new SellWindow((i+1) + "号窗口"));
        }
    }

    public static class SellWindow implements Callable<Object> {

        private static AtomicInteger tickets = new AtomicInteger(120);

        private String windowName;
        private int count;

        public SellWindow(String windowName) {
            this.windowName = windowName;
        }

        @Override
        public Object call() throws Exception {
            int retain = 0;
            while((retain=tickets.addAndGet(-1))>=0) {
                ++count;
                System.out.println(windowName +"售出1张票,剩余: " + retain + "张");
            }
            System.out.println("票已售完," + windowName + "暂停服务, 共售出:" + count + "张票");
            return null;
        }
    }
}

运行结果如下 :

2号窗口售出1张票,剩余: 118张
4号窗口售出1张票,剩余: 116张
3号窗口售出1张票,剩余: 117张
1号窗口售出1张票,剩余: 119张
3号窗口售出1张票,剩余: 113张
4号窗口售出1张票,剩余: 114张
4号窗口售出1张票,剩余: 110张
2号窗口售出1张票,剩余: 115张
4号窗口售出1张票,剩余: 109张
3号窗口售出1张票,剩余: 111张
1号窗口售出1张票,剩余: 112张
3号窗口售出1张票,剩余: 106张
4号窗口售出1张票,剩余: 107张
2号窗口售出1张票,剩余: 108张
4号窗口售出1张票,剩余: 103张
3号窗口售出1张票,剩余: 104张
1号窗口售出1张票,剩余: 105张
3号窗口售出1张票,剩余: 100张
4号窗口售出1张票,剩余: 101张
2号窗口售出1张票,剩余: 102张
4号窗口售出1张票,剩余: 97张
3号窗口售出1张票,剩余: 98张
1号窗口售出1张票,剩余: 99张
3号窗口售出1张票,剩余: 94张
4号窗口售出1张票,剩余: 95张
2号窗口售出1张票,剩余: 96张
4号窗口售出1张票,剩余: 91张
3号窗口售出1张票,剩余: 92张
1号窗口售出1张票,剩余: 93张
3号窗口售出1张票,剩余: 88张
3号窗口售出1张票,剩余: 86张
3号窗口售出1张票,剩余: 85张
3号窗口售出1张票,剩余: 84张
3号窗口售出1张票,剩余: 83张
3号窗口售出1张票,剩余: 82张
3号窗口售出1张票,剩余: 81张
3号窗口售出1张票,剩余: 80张
3号窗口售出1张票,剩余: 79张
3号窗口售出1张票,剩余: 78张
3号窗口售出1张票,剩余: 77张
3号窗口售出1张票,剩余: 76张
3号窗口售出1张票,剩余: 75张
3号窗口售出1张票,剩余: 74张
3号窗口售出1张票,剩余: 73张
3号窗口售出1张票,剩余: 72张
3号窗口售出1张票,剩余: 71张
3号窗口售出1张票,剩余: 70张
3号窗口售出1张票,剩余: 69张
3号窗口售出1张票,剩余: 68张
3号窗口售出1张票,剩余: 67张
3号窗口售出1张票,剩余: 66张
3号窗口售出1张票,剩余: 65张
3号窗口售出1张票,剩余: 64张
3号窗口售出1张票,剩余: 63张
3号窗口售出1张票,剩余: 62张
3号窗口售出1张票,剩余: 61张
3号窗口售出1张票,剩余: 60张
3号窗口售出1张票,剩余: 59张
3号窗口售出1张票,剩余: 58张
3号窗口售出1张票,剩余: 57张
4号窗口售出1张票,剩余: 89张
2号窗口售出1张票,剩余: 90张
4号窗口售出1张票,剩余: 55张
4号窗口售出1张票,剩余: 53张
4号窗口售出1张票,剩余: 52张
4号窗口售出1张票,剩余: 51张
4号窗口售出1张票,剩余: 50张
4号窗口售出1张票,剩余: 49张
4号窗口售出1张票,剩余: 48张
4号窗口售出1张票,剩余: 47张
4号窗口售出1张票,剩余: 46张
4号窗口售出1张票,剩余: 45张
4号窗口售出1张票,剩余: 44张
4号窗口售出1张票,剩余: 43张
4号窗口售出1张票,剩余: 42张
4号窗口售出1张票,剩余: 41张
3号窗口售出1张票,剩余: 56张
1号窗口售出1张票,剩余: 87张
3号窗口售出1张票,剩余: 39张
4号窗口售出1张票,剩余: 40张
2号窗口售出1张票,剩余: 54张
4号窗口售出1张票,剩余: 36张
3号窗口售出1张票,剩余: 37张
1号窗口售出1张票,剩余: 38张
3号窗口售出1张票,剩余: 33张
4号窗口售出1张票,剩余: 34张
2号窗口售出1张票,剩余: 35张
4号窗口售出1张票,剩余: 30张
4号窗口售出1张票,剩余: 28张
4号窗口售出1张票,剩余: 27张
4号窗口售出1张票,剩余: 26张
3号窗口售出1张票,剩余: 31张
1号窗口售出1张票,剩余: 32张
1号窗口售出1张票,剩余: 23张
3号窗口售出1张票,剩余: 24张
4号窗口售出1张票,剩余: 25张
2号窗口售出1张票,剩余: 29张
4号窗口售出1张票,剩余: 20张
3号窗口售出1张票,剩余: 21张
1号窗口售出1张票,剩余: 22张
3号窗口售出1张票,剩余: 17张
4号窗口售出1张票,剩余: 18张
2号窗口售出1张票,剩余: 19张
4号窗口售出1张票,剩余: 14张
3号窗口售出1张票,剩余: 15张
1号窗口售出1张票,剩余: 16张
1号窗口售出1张票,剩余: 10张
1号窗口售出1张票,剩余: 9张
1号窗口售出1张票,剩余: 8张
1号窗口售出1张票,剩余: 7张
1号窗口售出1张票,剩余: 6张
1号窗口售出1张票,剩余: 5张
1号窗口售出1张票,剩余: 4张
1号窗口售出1张票,剩余: 3张
1号窗口售出1张票,剩余: 2张
1号窗口售出1张票,剩余: 1张
1号窗口售出1张票,剩余: 0张
票已售完,1号窗口暂停服务, 共售出:22张票
3号窗口售出1张票,剩余: 11张
票已售完,3号窗口暂停服务, 共售出:50张票
4号窗口售出1张票,剩余: 12张
票已售完,4号窗口暂停服务, 共售出:37张票
2号窗口售出1张票,剩余: 13张
票已售完,2号窗口暂停服务, 共售出:11张票

直接可运行
如有帮助,请采纳,十分感谢!

可以看看我的java多线程篇?%ra=linkhttps://blog.csdn.net/m0_56981185/article/details/123792758

循环加锁判断数量是否大于等于1


import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class Test9_2 extends JFrame implements ActionListener
{
//    多线程试验。模拟航班售票系统,实现4个售票窗口发售某班次航班的100张机票,
//
//    一个售票窗口用一个线程表示。要求不能重复发售。

    public Button b_start=new Button("开始售卖");
    public s_panel s1=new s_panel(50,100,1,25);
    public s_panel s2=new s_panel(50,200,26,50);
    public s_panel s3=new s_panel(50,300,51,75);
    public s_panel s4=new s_panel(50,400,76,100);
    public static int id=1;
    public Test9_2()//构造方法
    {
        super("五一黄金周机票售卖");
        setBounds(100,100,700,550);

        add(b_start);
        b_start.addActionListener( this);
        b_start.setBounds(20,50,70,20);
        add(s2);
        add(s1);
        add(s3);
        add(s4);
        setLayout(null);
        setVisible(true);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    }
    public static void main(String[] args)
    {
        new Test9_2();
    }

    @Override
    public void actionPerformed(ActionEvent e) {

        b_start.setEnabled(false);
        ExecutorService exec= Executors.newCachedThreadPool();
        exec.execute(s1);
        exec.execute(s2);
        exec.execute(s3);
        exec.execute(s4);

        exec.shutdown();
    }
}

class s_panel extends JPanel implements Runnable
{
    protected int x,y;
    protected int max;
    protected int min;
    protected JLabel s_Label=new JLabel("售票窗口"+Test9_2.id+++"已售出票号:");
    protected JTextField s_TextField=new JTextField(40);
    protected int[] nums =new int[120];
    //protected int[] nums =new int[25];错误示例
    public s_panel(int x,int y,int min,int max)
    {
        this.x=x;
        this.y=y;
        this.max=max;
        this.min=min;
        setBounds(x,y,500,100);
        add(s_Label);
        add(s_TextField);
        s_TextField.setEditable(false);
    }
    @Override
    public void run()
    {
        try
        {
            for(int i=min;i<=max;)
            {

                int flag=1;
                int num=(int)(Math.random()*max+1);
                //int num=(int)(Math.random()*max+1)-min+1;错误示例
                //JOptionPane.showMessageDialog(null,num);
                for(int j=min;j<=i;j++)//判断num是否符合条件
                {
                    if (num == nums[j - 1] || num < min || num > max)
                    {
                        flag = 0;
                        break;
                    }

                }
                if(flag==1)
                {
                    //JOptionPane.showMessageDialog(null,num);
                    nums[i-1]=num;
                    String temp=s_TextField.getText();
                    s_TextField.setText(temp+" "+num);
                    TimeUnit.MILLISECONDS.sleep(100);
                    i++;
                }

            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

public class TestThread {
    public static void main(String[] args) {
        Window window1 = new Window();
        window1.setName("窗口1");
        Window window2 = new Window();
        window2.setName("窗口2");
        Window window3 = new Window();
        window3.setName("窗口3");
        Window window4 = new Window();
        window3.setName("窗口4");
        window1.start();
        window2.start();
        window3.start();
        window4.start();
    }

}

class Window extends Thread{
    static int ticket = 120;
    @Override
    public void run() {
        while (true){
            if(ticket > 0){
                System.out.println(Thread.currentThread().getName() + "卖票,票号"+ticket--);
            } else {
                break;
            }
        }

    }
}