• Java之多线程综合练习小题一


    2. 多线程综合练习

    练习一:售票

    需求:

    一共有1000张电影票,可以在两个窗口领取,假设每次领取的时间为3000毫秒,

    请用多线程模拟卖票过程并打印剩余电影票的数量

    代码示例:

    1. public class MyThread extends Thread {
    2.    //第一种方式实现多线程,测试类中MyThread会创建多次,所以需要加static
    3.    static int ticket = 1000;
    4.    @Override
    5.    public void run() {
    6.        //1.循环
    7.        while (true) {
    8.            //2.同步代码块
    9.            synchronized (MyThread.class) {
    10.                //3.判断共享数据(已经到末尾)
    11.                if (ticket == 0) {
    12.                    break;
    13.               } else {
    14.                    //4.判断共享数据(没有到末尾)
    15.                    try {
    16.                        Thread.sleep(3000);
    17.                   } catch (InterruptedException e) {
    18.                        e.printStackTrace();
    19.                   }
    20.                    ticket--;
    21.                    System.out.println(getName() + "在卖票,还剩下" + ticket + "张票!!!");
    22.               }
    23.           }
    24.       }
    25.   }
    26. }
    27. public class Test {
    28.    public static void main(String[] args) {
    29.       /*
    30.            一共有1000张电影票,可以在两个窗口领取,假设每次领取的时间为3000毫秒,
    31.            要求:请用多线程模拟卖票过程并打印剩余电影票的数量
    32.        */
    33.        //创建线程对象
    34.        MyThread t1 = new MyThread();
    35.        MyThread t2 = new MyThread();
    36.        //给线程设置名字
    37.        t1.setName("窗口1");
    38.        t2.setName("窗口2");
    39.        //开启线程
    40.        t1.start();
    41.        t2.start();
    42.   }
    43. }

    练习二:赠送礼物

    需求:

    有100份礼品,两人同时发送,当剩下的礼品小于10份的时候则不再送出。

    利用多线程模拟该过程并将线程的名字和礼物的剩余数量打印出来.

    1. public class MyRunable implements Runnable {
    2.    //第二种方式实现多线程,测试类中MyRunable只创建一次,所以不需要加static
    3.    int count = 100;
    4.    @Override
    5.    public void run() {
    6.        //1.循环
    7.        while (true) {
    8.            //2.同步代码块
    9.            synchronized (MyThread.class) {
    10.                //3.判断共享数据(已经到末尾)
    11.                if (count < 10) {
    12.                    System.out.println("礼物还剩下" + count + "不再赠送");
    13.                    break;
    14.               } else {
    15.                    //4.判断共享数据(没有到末尾)
    16.                    count--;
    17.                    System.out.println(Thread.currentThread().getName() + "在赠送礼物,还剩下" + count + "个礼物!!!");
    18.               }
    19.           }
    20.       }
    21.   }
    22. }
    23. public class Test {
    24.    public static void main(String[] args) {
    25.        /*
    26.            有100份礼品,两人同时发送,当剩下的礼品小于10份的时候则不再送出,
    27.            利用多线程模拟该过程并将线程的名字和礼物的剩余数量打印出来.
    28.        */
    29.        //创建参数对象
    30.        MyRunable mr = new MyRunable();
    31.        //创建线程对象
    32.        Thread t1 = new Thread(mr,"窗口1");
    33.        Thread t2 = new Thread(mr,"窗口2");
    34.        //启动线程
    35.        t1.start();
    36.        t2.start();
    37.   }
    38. }

    练习三:打印数字

    需求:

    同时开启两个线程,共同获取1-100之间的所有数字。

    将输出所有的奇数。

    1. public class MyRunable implements Runnable {
    2.    //第二种方式实现多线程,测试类中MyRunable只创建一次,所以不需要加static
    3.    int number = 1;
    4.    @Override
    5.    public void run() {
    6.        //1.循环
    7.        while (true) {
    8.            //2.同步代码块
    9.            synchronized (MyThread.class) {
    10.                //3.判断共享数据(已经到末尾)
    11.                if (number > 100) {
    12.                    break;
    13.               } else {
    14.                    //4.判断共享数据(没有到末尾)
    15.                    if(number % 2 == 1){
    16.                        System.out.println(Thread.currentThread().getName() + "打印数字" + number);
    17.                   }
    18.                    number++;
    19.               }
    20.           }
    21.       }
    22.   }
    23. }
    24. public class Test {
    25.    public static void main(String[] args) {
    26.        /*
    27.           同时开启两个线程,共同获取1-100之间的所有数字。
    28.           要求:将输出所有的奇数。
    29.        */
    30.        //创建参数对象
    31.        MyRunable mr = new MyRunable();
    32.        //创建线程对象
    33.        Thread t1 = new Thread(mr,"线程A");
    34.        Thread t2 = new Thread(mr,"线程B");
    35.        //启动线程
    36.        t1.start();
    37.        t2.start();
    38.   }
    39. }

    练习四:抢红包

    需求:

    抢红包也用到了多线程。

    假设:100块,分成了3个包,现在有5个人去抢。

    其中,红包是共享数据。

    5个人是5条线程。

    打印结果如下:

    XXX抢到了XXX元

    XXX抢到了XXX元

    XXX抢到了XXX元

    XXX没抢到

    XXX没抢到

    解决方案一:

    1. public class MyThread extends Thread{
    2.    //共享数据
    3.    //100块,分成了3个包
    4.    static double money = 100;
    5.    static int count = 3;
    6.    //最小的中奖金额
    7.    static final double MIN = 0.01;
    8.    @Override
    9.    public void run() {
    10.        //同步代码块
    11.        synchronized (MyThread.class){
    12.            if(count == 0){
    13.                //判断,共享数据是否到了末尾(已经到末尾)
    14.                System.out.println(getName() + "没有抢到红包!");
    15.           }else{
    16.                //判断,共享数据是否到了末尾(没有到末尾)
    17.                //定义一个变量,表示中奖的金额
    18.                double prize = 0;
    19.                if(count == 1){
    20.                    //表示此时是最后一个红包
    21.                    //就无需随机,剩余所有的钱都是中奖金额
    22.                    prize = money;
    23.               }else{
    24.                    //表示第一次,第二次(随机)
    25.                    Random r = new Random();
    26.                    //100 元   3个包
    27.                    //第一个红包:99.98
    28.                    //100 - (3-1) * 0.01
    29.                    double bounds = money - (count - 1) * MIN;
    30.                    prize = r.nextDouble(bounds);
    31.                    if(prize < MIN){
    32.                        prize = MIN;
    33.                   }
    34.               }
    35.                //从money当中,去掉当前中奖的金额
    36.                money = money - prize;
    37.                //红包的个数-1
    38.                count--;
    39.                //本次红包的信息进行打印
    40.                System.out.println(getName() + "抢到了" + prize + "元");
    41.           }
    42.       }
    43.   }
    44. }
    45. public class Test {
    46.    public static void main(String[] args) {
    47.        /*
    48.            微信中的抢红包也用到了多线程。
    49.            假设:100块,分成了3个包,现在有5个人去抢。
    50.            其中,红包是共享数据。
    51.            5个人是5条线程。
    52.            打印结果如下:
    53.           XXX抢到了XXX元
    54.           XXX抢到了XXX元
    55.           XXX抢到了XXX元
    56.           XXX没抢到
    57.           XXX没抢到
    58.        */
    59.        //创建线程的对象
    60.        MyThread t1 = new MyThread();
    61.        MyThread t2 = new MyThread();
    62.        MyThread t3 = new MyThread();
    63.        MyThread t4 = new MyThread();
    64.        MyThread t5 = new MyThread();
    65.        //给线程设置名字
    66.        t1.setName("小A");
    67.        t2.setName("小QQ");
    68.        t3.setName("小哈哈");
    69.        t4.setName("小诗诗");
    70.        t5.setName("小丹丹");
    71.        //启动线程
    72.        t1.start();
    73.        t2.start();
    74.        t3.start();
    75.        t4.start();
    76.        t5.start();
    77.   }
    78. }

    解决方案二:

    1. public class MyThread extends Thread{
    2.    //总金额
    3.    static BigDecimal money = BigDecimal.valueOf(100.0);
    4.    //个数
    5.    static int count = 3;
    6.    //最小抽奖金额
    7.    static final BigDecimal MIN = BigDecimal.valueOf(0.01);
    8.    @Override
    9.    public void run() {
    10.        synchronized (MyThread.class){
    11.            if(count == 0){
    12.                System.out.println(getName() + "没有抢到红包!");
    13.           }else{
    14.                //中奖金额
    15.                BigDecimal prize;
    16.                if(count == 1){
    17.                    prize = money;
    18.               }else{
    19.                    //获取抽奖范围
    20.                    double bounds = money.subtract(BigDecimal.valueOf(count-1).multiply(MIN)).doubleValue();
    21.                    Random r = new Random();
    22.                    //抽奖金额
    23.                    prize = BigDecimal.valueOf(r.nextDouble(bounds));
    24.               }
    25.                //设置抽中红包,小数点保留两位,四舍五入
    26.                prize = prize.setScale(2,RoundingMode.HALF_UP);
    27.                //在总金额中去掉对应的钱
    28.                money = money.subtract(prize);
    29.                //红包少了一个
    30.                count--;
    31.                //输出红包信息
    32.                System.out.println(getName() + "抽中了" + prize + "元");
    33.           }
    34.       }
    35.   }
    36. }
    37. public class Test {
    38.    public static void main(String[] args) {
    39.        /*
    40.            微信中的抢红包也用到了多线程。
    41.            假设:100块,分成了3个包,现在有5个人去抢。
    42.            其中,红包是共享数据。
    43.            5个人是5条线程。
    44.            打印结果如下:
    45.           XXX抢到了XXX元
    46.           XXX抢到了XXX元
    47.           XXX抢到了XXX元
    48.           XXX没抢到
    49.           XXX没抢到
    50.        */
    51.        MyThread t1 = new MyThread();
    52.        MyThread t2 = new MyThread();
    53.        MyThread t3 = new MyThread();
    54.        MyThread t4 = new MyThread();
    55.        MyThread t5 = new MyThread();
    56.        t1.setName("小A");
    57.        t2.setName("小QQ");
    58.        t3.setName("小哈哈");
    59.        t4.setName("小诗诗");
    60.        t5.setName("小丹丹");
    61.        t1.start();
    62.        t2.start();
    63.        t3.start();
    64.        t4.start();
    65.        t5.start();
    66.   }
    67. }

    练习五:抽奖箱

    需求:

    有一个抽奖池,该抽奖池中存放了奖励的金额,该抽奖池中的奖项为 {10,5,20,50,100,200,500,800,2,80,300,700};

    创建两个抽奖箱(线程)设置线程名称分别为“抽奖箱1”,“抽奖箱2”

    随机从抽奖池中获取奖项元素并打印在控制台上,格式如下:

    每次抽出一个奖项就打印一个(随机)

    抽奖箱1 又产生了一个 10 元大奖

    抽奖箱1 又产生了一个 100 元大奖

    抽奖箱1 又产生了一个 200 元大奖

    抽奖箱1 又产生了一个 800 元大奖

    抽奖箱2 又产生了一个 700 元大奖

    .....

    1. public class MyThread extends Thread {
    2.    ArrayList list;
    3.    public MyThread(ArrayList list) {
    4.        this.list = list;
    5.   }
    6.    @Override
    7.    public void run() {
    8.        //1.循环
    9.        //2.同步代码块
    10.        //3.判断
    11.        //4.判断
    12.        while (true) {
    13.            synchronized (MyThread.class) {
    14.                if (list.size() == 0) {
    15.                    break;
    16.               } else {
    17.                    //继续抽奖
    18.                    Collections.shuffle(list);
    19.                    int prize = list.remove(0);
    20.                    System.out.println(getName() + "又产生了一个" + prize + "元大奖");
    21.               }
    22.           }
    23.            try {
    24.                Thread.sleep(10);
    25.           } catch (InterruptedException e) {
    26.                e.printStackTrace();
    27.           }
    28.       }
    29.   }
    30. }
    31. public class Test {
    32.    public static void main(String[] args) {
    33.        /*
    34.            有一个抽奖池,该抽奖池中存放了奖励的金额,该抽奖池中的奖项为 {10,5,20,50,100,200,500,800,2,80,300,700};
    35.            创建两个抽奖箱(线程)设置线程名称分别为“抽奖箱1”,“抽奖箱2”
    36.            随机从抽奖池中获取奖项元素并打印在控制台上,格式如下:
    37.                             每次抽出一个奖项就打印一个(随机)
    38.           抽奖箱1 又产生了一个 10 元大奖
    39.           抽奖箱1 又产生了一个 100 元大奖
    40.           抽奖箱1 又产生了一个 200 元大奖
    41.           抽奖箱1 又产生了一个 800 元大奖
    42.           抽奖箱2 又产生了一个 700 元大奖
    43.           .....
    44.        */
    45.        //创建奖池
    46.        ArrayList list = new ArrayList<>();
    47.        Collections.addAll(list,10,5,20,50,100,200,500,800,2,80,300,700);
    48.        //创建线程
    49.        MyThread t1 = new MyThread(list);
    50.        MyThread t2 = new MyThread(list);
    51.        //设置名字
    52.        t1.setName("抽奖箱1");
    53.        t2.setName("抽奖箱2");
    54.        //启动线程
    55.        t1.start();
    56.        t2.start();
    57.   }
    58. }

  • 相关阅读:
    mysql性能优化之数据类型(持续更新)
    Java:修改Jar的源码,并上传Nexus私有仓库,替换jar版本
    CentOS7 设置固定IP地址
    Node学习二十 —— 构建和使用HTTP中间件
    centos7桌面版下载向日葵和todesk
    Rsync分布式应用
    Visio画图更改连接线的弧形和调整跨线
    java反射全面复习
    【中央任务调度系统—通信开发】
    进阶指针(三)--- qsort函数(快速排序)的使用和(用冒泡排序)模拟实现
  • 原文地址:https://blog.csdn.net/qq_69748833/article/details/133470575