Java多线程习题集(尚硅谷)求解

题目1:

模拟一个人生产50个玩具,每200毫秒生产一个,当生产到第20个时加入每秒吃1个馒头,共吃完3个后在接着生产的多线程。

分析:

以下是单线程的写法,题目要求使用多线程,待改正

代码如下:

/**
 * 模拟一个人生产50个玩具,每200毫秒生产一个,当生产到第20个时加入每秒
 * 吃1个馒头,共吃完3个后在接着生产的多线程。
 * @author Microdust
 * @create 2020/11/25-9:39
 */
class People implements Runnable{
    private int toy = 0;
    private int bread = 3;

    @Override
    public void run() {
        while (toy < 50){
            if (toy == 20){
                while (bread > 0){
                    eatBread();
                }
            }
                produceToy();
        }
    }

    public synchronized void produceToy(){
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() +
                ":正在生产玩具" + (toy + 1));
        toy++;
    }

    public synchronized void eatBread(){
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() +
                ":正在吃面包!");
        bread--;
    }
}
public class PeopleTest {
    public static void main(String[] args) {
        People p = new People();
        Thread t = new Thread(p);
        t.setName("Microdust");
        t.start();
    }

}

题目2:

启动两个线程对一个数字i操作

  1. 其中1个线程每次对i加1
  2. 另1个线程每次对i减1
    各运行20次,结果i的值等于初始值。

分析:

1.线程同步的问题,一个线程在操作数据时另一个线程不能进入,可以想到使用synchronized或者Lock

2.第一反应肯定能想到实现两个线程,使用Integer包装类的对象作为synchronized代码块的同步监视器。

3.实践后发现,如果在main()方法中声明的Integer对象作为参数传入实现Runnable对象的构造器后,调用new Thread(Runnable r).start(),两个线程并不能共享一个同步监视器,会在run()方法体中使用各自的同步监视器,会让结果异常。

4.这里应该将数字i作为一个属性封装在另一个Number类中,并使用Number类的对象作为同步监视器,这样可以使得多个线程共用一个同步监视器。

代码如下:

/**
 * 启动两个线程对一个数字i操作
 * 1)	其中1个线程每次对i加1
 * 2)	另1个线程每次对i减1
 * 各运行20次,结果i的值等于初始值。
 * @author Microdust
 * @create 2020/11/25-9:59
 */
class Number{
    private static int i = 0;

    public Number(int i){
        this.i = i;
    }

    public int getI() {
        return i;
    }

    public void setI(int i) {
        this.i = i;
    }
    public void add(){
        i++;
    }
    public void sub(){
        i--;
    }
}
class MyThreadAdd implements Runnable {
    private Number num;

    public MyThreadAdd(Number num) {
        this.num = num;
    }

    @Override
    public void run() {
        for (int j = 0; j < 20; j++) {
            synchronized (num) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                num.add();
                System.out.println(Thread.currentThread().getName() +
                        ",i = " + num.getI());
            }
        }

    }
}
class MyThreadSub implements Runnable {
    private Number num;

    public MyThreadSub(Number num) {
        this.num = num;
    }

    @Override
    public void run() {
        for (int j = 0; j < 20; j++) {
            synchronized (num) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                num.sub();
                System.out.println(Thread.currentThread().getName() +
                        ",i = " + num.getI());
            }
        }

    }
}
public class ThreadTest1 {
    public static void main(String[] args) {
        Number num = new Number(0);

        MyThreadAdd add = new MyThreadAdd(num);
        MyThreadSub sub = new MyThreadSub(num);
        Thread t1 = new Thread(add);
        Thread t2 = new Thread(sub);
        System.out.println("i = " + num.getI());
        t1.setName("add");
        t2.setName("sub");
        t1.start();
        t2.start();
        try {
            t1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        try {
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("i = " + num.getI());
    }
}

题目3:

模拟3个人排除买票,每人买1张票。售货员只有1张五元的钱,电影票5元一张,王大拿拿一张二十元的人民币排在谢大脚前面买票,谢大脚拿1张十元的人民币排在在赵四的前面买票,赵四拿1张五元的人民币排在最后。即最终的卖票次序是:谢大脚、赵四、王大拿

分析:

多线程同步问题。

代码如下:

/**
 * 模拟3个人排除买票,每人买1张票。
 * 售货员只有1张五元的钱,电影票5元一张,
 * 王大拿拿一张二十元的人民币排在谢大脚前面买票,
 * 谢大脚拿1张十元的人民币排在在赵四的前面买票,
 * 赵四拿1张五元的人民币排在最后。
 * 即最终的卖票次序是:谢大脚、赵四、王大拿
 * @author Microdust
 * @create 2020/11/25-15:09
 */
class SalesMan{
    private int money = 5;
    private int price = 5;
    public void addMoney(){
        money += price;
    }
    public int getMoney() {
        return money;
    }

    public void setMoney(int money) {
        this.money = money;
    }

    public boolean canBuyTicket(int money){
        if (this.money >= money - price){
            return true;
        }else{
            return false;
        }
    }
}
class BuyTicket implements Runnable{
    private int money;
    private int ticket = 0;
    private SalesMan salesMan;
    public BuyTicket(int money,SalesMan salesMan){
        this.money = money;
        this.salesMan = salesMan;
    }
    @Override
    public void run() {
        while (ticket == 0){
            synchronized (salesMan){
                if (salesMan.canBuyTicket(money)){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    salesMan.addMoney();
                    ticket++;
                    System.out.println(Thread.currentThread().getName()
                            + ":买到一张票!");
                }
            }
        }
    }
}
public class ThreadTest2 {
    public static void main(String[] args) {
        SalesMan salesMan = new SalesMan();
        BuyTicket b1 = new BuyTicket(20,salesMan);
        BuyTicket b2 = new BuyTicket(10,salesMan);
        BuyTicket b3 = new BuyTicket(5,salesMan);
        Thread t1 = new Thread(b1);
        Thread t2 = new Thread(b2);
        Thread t3 = new Thread(b3);
        t1.setName("王大拿");
        t2.setName("谢大脚");
        t3.setName("赵四");
        t1.start();
        t2.start();
        t3.start();
    }

}

题目4:

编写生产者消费者多线程程序,设有一个最大库存量为4的电视机仓库,生产10台电视机,一边生产一边销售(消费)。

分析:

生产者消费者问题。

代码如下:

/**
 * 编写生产者消费者多线程程序,设有一个最大库存量为4的电视机仓库,
 * 生产10台电视机,一边生产一边销售(消费)。
 * @author Microdust
 * @create 2020/11/25-16:08
 */
class WareHouse{
    private final static int MAX_COUNTS = 4;
    private int nums = 0;

    public synchronized boolean producerProduce(){
        if (nums < MAX_COUNTS){
            nums++;
            System.out.println(Thread.currentThread().getName() +
                    ":开始生产第" + nums + "个电视");
            notify();
            return true;
        }else{
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return false;
        }
    }
    public synchronized boolean consumerConsume(){
        if (nums > 0){
            System.out.println(Thread.currentThread().getName() +
                    ":开始销售第" + nums + "个电视");
            nums--;
            notify();
            return true;
        }else{
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return false;
        }
    }
}
class Producer extends Thread{
    private WareHouse wareHouse;
    private int count = 0;
    public Producer(WareHouse wareHouse){this.wareHouse = wareHouse;}
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() +
                "开始生产...");
        while (count != 10) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (wareHouse.producerProduce()){
                count++;
            };

        }
    }
}
class Consumer extends Thread{
    private WareHouse wareHouse;
    private int count = 0;
    public Consumer(WareHouse wareHouse){this.wareHouse = wareHouse;}
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() +
                "开始消费...");
        while (count != 10) {
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (wareHouse.consumerConsume()){
                count++;
            };
        }
    }
}
public class ProductorTest {
    public static void main(String[] args) {
        WareHouse wareHouse = new WareHouse();
        Producer p1 = new Producer(wareHouse);
        Consumer c1 = new Consumer(wareHouse);
        p1.setName("生产者1");
        c1.setName("消费者1");
        p1.start();
        c1.start();
    }

}
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值