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

2. 多线程综合练习

练习一:售票

需求:

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

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

代码示例:

public class MyThread extends Thread {
​
    //第一种方式实现多线程,测试类中MyThread会创建多次,所以需要加static
    static int ticket = 1000;
​
    @Override
    public void run() {
        //1.循环
        while (true) {
            //2.同步代码块
            synchronized (MyThread.class) {
                //3.判断共享数据(已经到末尾)
                if (ticket == 0) {
                    break;
                } else {
                    //4.判断共享数据(没有到末尾)
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    ticket--;
                    System.out.println(getName() + "在卖票,还剩下" + ticket + "张票!!!");
                }
            }
        }
    }
}
​
public class Test {
    public static void main(String[] args) {
       /*
            一共有1000张电影票,可以在两个窗口领取,假设每次领取的时间为3000毫秒,
            要求:请用多线程模拟卖票过程并打印剩余电影票的数量
        */
​
        //创建线程对象
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
​
        //给线程设置名字
        t1.setName("窗口1");
        t2.setName("窗口2");
​
        //开启线程
        t1.start();
        t2.start();
​
    }
}

练习二:赠送礼物

需求:

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

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

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

练习三:打印数字

需求:

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

将输出所有的奇数。

public class MyRunable implements Runnable {
​
    //第二种方式实现多线程,测试类中MyRunable只创建一次,所以不需要加static
    int number = 1;
​
    @Override
    public void run() {
        //1.循环
        while (true) {
            //2.同步代码块
            synchronized (MyThread.class) {
                //3.判断共享数据(已经到末尾)
                if (number > 100) {
                    break;
                } else {
                    //4.判断共享数据(没有到末尾)
                    if(number % 2 == 1){
                        System.out.println(Thread.currentThread().getName() + "打印数字" + number);
                    }
                    number++;
                }
            }
        }
    }
}
​
​
public class Test {
    public static void main(String[] args) {
        /*
           同时开启两个线程,共同获取1-100之间的所有数字。
           要求:将输出所有的奇数。
        */
​
​
        //创建参数对象
        MyRunable mr = new MyRunable();
​
        //创建线程对象
        Thread t1 = new Thread(mr,"线程A");
        Thread t2 = new Thread(mr,"线程B");
​
        //启动线程
        t1.start();
        t2.start();
    }
}

练习四:抢红包

需求:

抢红包也用到了多线程。

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

其中,红包是共享数据。

5个人是5条线程。

打印结果如下:

XXX抢到了XXX元

XXX抢到了XXX元

XXX抢到了XXX元

XXX没抢到

XXX没抢到

解决方案一:

public class MyThread extends Thread{
​
    //共享数据
    //100块,分成了3个包
    static double money = 100;
    static int count = 3;
​
    //最小的中奖金额
    static final double MIN = 0.01;
​
    @Override
    public void run() {
        //同步代码块
        synchronized (MyThread.class){
            if(count == 0){
                //判断,共享数据是否到了末尾(已经到末尾)
                System.out.println(getName() + "没有抢到红包!");
            }else{
                //判断,共享数据是否到了末尾(没有到末尾)
                //定义一个变量,表示中奖的金额
                double prize = 0;
                if(count == 1){
                    //表示此时是最后一个红包
                    //就无需随机,剩余所有的钱都是中奖金额
                    prize = money;
                }else{
                    //表示第一次,第二次(随机)
                    Random r = new Random();
                    //100 元   3个包
                    //第一个红包:99.98
                    //100 - (3-1) * 0.01
                    double bounds = money - (count - 1) * MIN;
                    prize = r.nextDouble(bounds);
                    if(prize < MIN){
                        prize = MIN;
                    }
                }
                //从money当中,去掉当前中奖的金额
                money = money - prize;
                //红包的个数-1
                count--;
                //本次红包的信息进行打印
                System.out.println(getName() + "抢到了" + prize + "元");
            }
        }
    }
}
public class Test {
    public static void main(String[] args) {
        /*
            微信中的抢红包也用到了多线程。
            假设:100块,分成了3个包,现在有5个人去抢。
            其中,红包是共享数据。
            5个人是5条线程。
            打印结果如下:
                XXX抢到了XXX元
                XXX抢到了XXX元
                XXX抢到了XXX元
                XXX没抢到
                XXX没抢到
        */
​
        //创建线程的对象
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        MyThread t3 = new MyThread();
        MyThread t4 = new MyThread();
        MyThread t5 = new MyThread();
​
        //给线程设置名字
        t1.setName("小A");
        t2.setName("小QQ");
        t3.setName("小哈哈");
        t4.setName("小诗诗");
        t5.setName("小丹丹");
​
        //启动线程
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();
    }
}

解决方案二:

public class MyThread extends Thread{
​
    //总金额
    static BigDecimal money = BigDecimal.valueOf(100.0);
    //个数
    static int count = 3;
    //最小抽奖金额
    static final BigDecimal MIN = BigDecimal.valueOf(0.01);
​
    @Override
    public void run() {
        synchronized (MyThread.class){
            if(count == 0){
                System.out.println(getName() + "没有抢到红包!");
            }else{
                //中奖金额
                BigDecimal prize;
                if(count == 1){
                    prize = money;
                }else{
                    //获取抽奖范围
                    double bounds = money.subtract(BigDecimal.valueOf(count-1).multiply(MIN)).doubleValue();
                    Random r = new Random();
                    //抽奖金额
                    prize = BigDecimal.valueOf(r.nextDouble(bounds));
                }
                //设置抽中红包,小数点保留两位,四舍五入
                prize = prize.setScale(2,RoundingMode.HALF_UP);
                //在总金额中去掉对应的钱
                money = money.subtract(prize);
                //红包少了一个
                count--;
                //输出红包信息
                System.out.println(getName() + "抽中了" + prize + "元");
            }
        }
    }
}
​
public class Test {
    public static void main(String[] args) {
        /*
            微信中的抢红包也用到了多线程。
            假设:100块,分成了3个包,现在有5个人去抢。
            其中,红包是共享数据。
            5个人是5条线程。
            打印结果如下:
                XXX抢到了XXX元
                XXX抢到了XXX元
                XXX抢到了XXX元
                XXX没抢到
                XXX没抢到
        */
​
​
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        MyThread t3 = new MyThread();
        MyThread t4 = new MyThread();
        MyThread t5 = new MyThread();
​
        t1.setName("小A");
        t2.setName("小QQ");
        t3.setName("小哈哈");
        t4.setName("小诗诗");
        t5.setName("小丹丹");
​
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();
    }
}

练习五:抽奖箱

需求:

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

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

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

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

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

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

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

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

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

.....

public class MyThread extends Thread {
​
    ArrayList list;
​
    public MyThread(ArrayList list) {
        this.list = list;
    }
​
    @Override
    public void run() {
        //1.循环
        //2.同步代码块
        //3.判断
        //4.判断
​
        while (true) {
            synchronized (MyThread.class) {
                if (list.size() == 0) {
                    break;
                } else {
                    //继续抽奖
                    Collections.shuffle(list);
                    int prize = list.remove(0);
                    System.out.println(getName() + "又产生了一个" + prize + "元大奖");
                }
            }
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
​
        }
    }
}
​
​
​
public class Test {
    public static void main(String[] args) {
        /*
            有一个抽奖池,该抽奖池中存放了奖励的金额,该抽奖池中的奖项为 {10,5,20,50,100,200,500,800,2,80,300,700};
            创建两个抽奖箱(线程)设置线程名称分别为“抽奖箱1”,“抽奖箱2”
            随机从抽奖池中获取奖项元素并打印在控制台上,格式如下:
                             每次抽出一个奖项就打印一个(随机)
                抽奖箱1 又产生了一个 10 元大奖
                抽奖箱1 又产生了一个 100 元大奖
                抽奖箱1 又产生了一个 200 元大奖
                抽奖箱1 又产生了一个 800 元大奖
                抽奖箱2 又产生了一个 700 元大奖
                .....
        */
​
        //创建奖池
        ArrayList list = new ArrayList<>();
        Collections.addAll(list,10,5,20,50,100,200,500,800,2,80,300,700);
​
        //创建线程
        MyThread t1 = new MyThread(list);
        MyThread t2 = new MyThread(list);
​
        //设置名字
        t1.setName("抽奖箱1");
        t2.setName("抽奖箱2");
​
        //启动线程
        t1.start();
        t2.start();
    }
}

你可能感兴趣的:(java,java,开发语言,笔记,多线程,练习)