JavaSE多线程小栗子

本文探讨了Java初试多线程中的两个实例:银行账户存款并发问题,以及经典的生产者消费者问题。通过这两个案例,展示了线程安全、同步机制和线程通信的重要性,并介绍了`synchronized`、`wait()`和`notify()`的使用。
摘要由CSDN通过智能技术生成

初试多线程:

小栗子1:

/**
 * @author nuo
 * @version 1.0
 * @description: TODO
 * @date 2021/12/10 17:03
 */

/*
 * 银行有一个账户。
 * 有两个储户分别向同一个账户存3000元,每次存1000,存3次。
 * 每次存完打印账户余额。
 * <p>
 * 分析:
 * 1.是否是多线程问题?是,两个储户线程
 * 2.是否有共享数据?有,账户(或账户余额)
 * 3.是否有线程安全问题?有
 * 4.需要考虑如何解决线程安全问题?同步机制:有三种方式。
 */

public class ThreadExer1 {
    public static void main(String[] args) {
        account acct = new account();
        new Thread(new consumer(acct)).start();
        new Thread(new consumer(acct)).start();
    }
}

class account{
    private int balance;

    public synchronized void deposit(double amount){
        if (amount > 0){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            balance += amount;
            System.out.println(Thread.currentThread() + "成功存入 :" + amount + "¥");
            System.out.println("账户余额 :" + balance);
        }
    }
}

class consumer implements Runnable {

    private account acct;

    public consumer(account acct) {
        this.acct = acct;
    }

    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            acct.deposit(1000);
        }
    }
}

小栗子2:

/**
 * @author nuo
 * @version 1.0
 * @description: TODO 线程通信的应用:经典例题:生产者/消费者问题
 * @date 2021/12/10 20:36
 */


/* 面试题:sleep() 和 wait()的异同?
*
* 1.相同点:一旦执行方法,都可以使得当前的线程进入阻塞状态。
*
* 2.不同点:
*          1)两个方法声明的位置不同:Thread类中声明sleep() , Object类中声明wait()
*          2)调用的要求不同:sleep()可以在任何需要的场景下调用。 wait()必须使用在同步代码块或同步方法中
*          3)关于是否释放同步监视器:如果两个方法都使用在同步代码块或同步方法中,sleep()不会释放锁,wait()会释放锁。
*/

/*
 * 线程通信的应用:经典例题:生产者/消费者问题
 *
 * 生产者(Producer)将产品交给店员(Clerk),而消费者(Customer)从店员处取走产品,
 * 店员一次只能持有固定数量的产品(比如:20),如果生产者试图生产更多的产品,
 * 店员会叫生产者停一下,如果店中有空位放产品了再通知生产者继续生产;
 * 如果店中没有产品了,店员会告诉消费者等一下,
 * 如果店中有产品了再通知消费者来取走产品。
 *
 * 分析:
 *      1.是否是多线程的问题?是,生产者的线程,消费者的线程
 *      2.是否有共享数据的问题?是,店员、产品、产品数
 *      3.如何解决线程的安全问题?同步机制,有三种方法
 *      4.是否涉及线程的通信?是
 */

public class ThreadExer2 {
    public static void main(String[] args) {
        Clerk c = new Clerk();
        Producer p = new Producer(c);
        Customer c_ = new Customer(c);

        new Thread(p).start();
        new Thread(c_).start();
    }
}

class Producer implements Runnable {

    private final Clerk c;

    public Producer(Clerk c) {
        this.c = c;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (c) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (c.getProduct() < 20) {
                    c.setProduct(c.getProduct() + 1);
                    System.out.println("生产者生产第" + c.getProduct() + "件产品...");
//                    必须使用同步监视器去调用
                    c.notify();
                }else {
                    try {
//                        必须使用同步监视器去调用
                        c.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}


class Customer implements Runnable {

    private final Clerk c;

    public Customer(Clerk c) {
        this.c = c;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (c) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (c.getProduct() > 0) {
                    System.out.println("消费者消费第" + c.getProduct() + "件产品...");
                    c.setProduct(c.getProduct() - 1);
//                    必须使用同步监视器去调用
                    c.notify();
                }else {
                    try {
//                        必须使用同步监视器去调用
                        c.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

class Clerk {
    private int product;

    public int getProduct() {
        return product;
    }

    public void setProduct(int product) {
        this.product = product;
    }
}

在这里插入图片描述

PS:
在调用相应的 wait() notify() 时,必须确保使用的是对应的同步监视器,未显示声明,则默认为当前对象 ( 非static 类型 ) 或当前类 ( static 类型 ) 调用

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值