java 多线程-2

如:

/**

  • 创建三个窗口买票,共100张票。用Runnable接口实现
    */
    public class RunMainRunnable {
    public static void main(String[] args) {
    Window window = new Window();
    // 创建三个线程
    Thread win1 = new Thread(window);
    Thread win2 = new Thread(window);
    Thread win3 = new Thread(window);
    // 设置线程的名字
    win1.setName(“窗口一:”);
    win2.setName(“窗口二:”);
    win3.setName(“窗口三:”);
    // 启动线程
    win1.start();
    win2.start();
    win3.start();
    }
    }

class Window implements Runnable{
private int ticket = 100; // 定义100张票
@Override
public void run() {
while (true) {
if (ticket > 0) {
try {
Thread.sleep(100); // 调用此方法,让效果明显一点
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+“获取到了第”+ticket+“票”);
ticket–;
}else{
break;
}
}
}
}
运行结果:出现了重票

问题分析:

之所以会出现重票、错票等问题,就是因为出现了线程不安全。【假设此时ticket=7】在if判断中,如当窗口一获得cpu后,首先判断ticket>0会真,执行打印语句输出“窗口一:获取到了第7票”,此时窗口二获得cpu【注意:窗口一并未执行“ticket–;”,ticket依然为7】,判断ticket>0为真,执行打印语句输出“窗口二:获取到了第7票”,此时窗口三获得cpu【注意:窗口二并未执行“ticket–;”,ticket依然为7】,判断ticket>0为真,执行打印语句输出“窗口三:获取到了第7票”。便会出现重票。这在实际生活当中,肯定是不允许的,那我们该如何解决线程的安全问题呢?

九、同步机制
在Java中,我们通过同步机制,来解决线程的安全问题。

方式一:同步代码块

synchronized(同步监视器){
//需要被同步的代码

}
说明:

什么是同步的代码?
操作共享数据的代码,即为需要被同步的代码。
什么是共享数据?
多个线程共同操作的变量。比如:ticket就是共享数据。
什么是同步监视器
俗称:锁。任何一个类的对象,都可以充当锁。
要求:多个线程必须要共用同一把锁。
方式二:同步方法

如果操作共享数据的代码完整的声明在一个方法中,我们不妨将此方法声明为同步的。
总结:

好处:同步的方式,解决了线程的安全问题。

坏处:操作同步代码时,只能有一个线程参与,其他线程等待。相当于是一个单线程的过程,效率低。 —局限性

eg1:方式一:同步代码块

/**

  • 创建三个窗口买票,共100张票。用Runnable接口实现
    */
    public class RunMainRunnable {
    public static void main(String[] args) {
    Window window = new Window();
    // 创建三个线程
    Thread win1 = new Thread(window);
    Thread win2 = new Thread(window);
    Thread win3 = new Thread(window);
    // 设置线程的名字
    win1.setName(“窗口一:”);
    win2.setName(“窗口二:”);
    win3.setName(“窗口三:”);
    // 启动线程
    win1.start();
    win2.start();
    win3.start();
    }
    }

/**

  • 方式一;同步代码块
    */
    class Window implements Runnable{
    private int ticket = 100; // 定义100张票
    private Object object = new Object();
    @Override
    public void run() {
    while (true) {
    synchronized (object){ // 同步代码块
    if (ticket > 0) {
    try {
    Thread.sleep(100); // 调用此方法,让效果明显一点
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName()+“获取到了第”+ticket+“票”);
    ticket–;
    }else{
    break;
    }
    }
    }
    }
    }

eg2:方式二:同步方法

/**

  • 创建三个窗口买票,共100张票。用Runnable接口实现
    */
    public class RunMainRunnable {
    public static void main(String[] args) {
    Window window = new Window();
    // 创建三个线程
    Thread win1 = new Thread(window);
    Thread win2 = new Thread(window);
    Thread win3 = new Thread(window);
    // 设置线程的名字
    win1.setName(“窗口一:”);
    win2.setName(“窗口二:”);
    win3.setName(“窗口三:”);
    // 启动线程
    win1.start();
    win2.start();
    win3.start();
    }
    }

/*
方式二;同步方法

  • */
    class Window implements Runnable{
    private int ticket = 100; // 定义100张票
    @Override
    public void run() {
    while (true) {
    show();// 调用同步方法
    if (ticket == 0) {
    break; // 用来结束循环
    }
    }
    }

    // 定义一个私有方法
    private synchronized void show() { // 加synchronized关键字,使其成为一位同步方法。同步监视器或锁即为:this
    if (ticket > 0) {
    try {
    Thread.sleep(100); // 调用此方法,让效果明显一点
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName()+“获取到了第”+ticket+“票”);
    ticket–;
    }
    }
    }

亚马逊测评 www.yisuping.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,您的问题是关于Java多线程的存钱取钱问题。这是一个经典的多线程同步问题,可以通过使用synchronized关键字来实现线程安全。下面是一个简单的示例代码: ```java public class BankAccount { private int balance; public BankAccount(int balance) { this.balance = balance; } public synchronized void deposit(int amount) { balance += amount; System.out.println("Deposit successful. Balance: " + balance); } public synchronized void withdraw(int amount) { if (balance < amount) { System.out.println("Withdraw failed. Insufficient balance."); return; } balance -= amount; System.out.println("Withdraw successful. Balance: " + balance); } } public class Main { public static void main(String[] args) { BankAccount account = new BankAccount(1000); // Create two threads to simulate deposit and withdraw Thread depositThread = new Thread(() -> { for (int i = 0; i < 5; i++) { account.deposit(100); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); Thread withdrawThread = new Thread(() -> { for (int i = 0; i < 5; i++) { account.withdraw(200); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); depositThread.start(); withdrawThread.start(); } } ``` 在这个示例代码中,我们创建了一个银行账户类BankAccount,并在其中实现了deposit和withdraw方法,并使用synchronized关键字来保证线程安全。 在main方法中,我们创建了两个线程来模拟存款和取款操作,每个线程执行5次操作。我们使用Thread.sleep方法来模拟每个操作之间的间隔,以便更好地观察多线程操作的结果。 当多个线程同时访问BankAccount对象的deposit和withdraw方法时,synchronized关键字可以确保每个方法只能被一个线程访问,从而避免了竞争条件和数据不一致的问题。 希望这个示例代码能够回答您的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值