当前位置: 首页 > 知识库问答 >
问题:

Java使用相同资源的非同步线程

钱毅
2023-03-14

我必须制作一个非常简化的联合银行账户程序(在这个例子中,有3个用户都可以访问银行账户资源),但是我在正确使用Java线程时遇到了问题。

以下是该程序的工作原理。有些“用户”都可以访问一个具有任意设置的初始余额的联合银行账户(我使用了5000)。他们每个人都可以在一次运行的程序中提取或存款三次(无论是提取还是存款,每次都是随机生成的)。

他们存款或取款的金额也是随机生成的,唯一的规则是金额永远不能超过当前余额的三分之一。

最后,在每个事务之后,当前线程必须“等待”1到10之间的随机秒数。

现在是令人困惑的部分。我们的老师要求我们创建一个独特的NotEnoughBalance异常类,以防其中一个用户以某种方式提取了比账户中当前更多的钱(但这是我的第一个困惑点:理论上,由于1/3规则,这永远不会发生)。

以下是发布在 pastebin 上的完整代码:

http://pastebin.com/Upam56NF

目前,当我运行main时:

public class BankAccount{
    public static void main(String[] args) throws InterruptedException{

        int capital = 5000;
        JointBankAccount acc = new JointBankAccount(capital);

        Thread t1 = new Thread(new Owner("Josh", acc));

        Thread t2 = new Thread(new Owner("Wade", acc));

        Thread t3 = new Thread(new Owner("Ben", acc));

        System.out.println(capital);
        String tname = Thread.currentThread().getName();
        System.out.println(tname);

        t1.start();
        t2.start();
        t3.start();

        t1.join();
        t2.join();
        t3.join();      

        for(AccountTransaction s : acc.history){
            System.out.println(s.toString());
        }
        System.out.println(acc.getBalance());
    }

}

我有时会在System.out.println(s.toString())中随机得到一个NPE异常。

如果我使存款和取款功能同步,这是完全可以修复的。

问题是,不知何故,我认为让它们同步违背了我们老师问的目的。如果我让它们同步,那么我觉得我在确保每次取款都能成功地遵循1/3规则,而不足够的余额例外永远不会存在。

当我删除synchronized时,我得到了NPE,这一事实也让我认为错误可能是我没有在异常发生时正确处理异常。我不知道。

任何帮助将不胜感激。

共有1个答案

轩辕嘉平
2023-03-14

在我看来,这是理解原子事务的一个很好的练习。

但首先是NPE:一个JointBankAccount实例在多个线程之间共享,因此JointBankAccount包含的任何内容都历史列表一样。历史列表的类型是 ArrayList,它不是线程安全的,即如果两个线程同时调用 add 方法,列表就会中断。不过这很容易解决:列出

现在是原子事务。由于余额可以随时被任何线程更改,所以在您读取余额的那一刻,余额就已经过时了。即像< code>if (balance

这遵循一个非常常见的模式:使用“廉价的”锁来确定事务是否可以完成(执行预检查),然后使用“昂贵的”锁来执行事务,但总是假设事务可能会失败,并在适当的时候重试事务。

 类似资料:
  • 10.4. 使用资源同步的事务 现在应该比较清楚的是:不同的事务管理器是如何创建的,以及它们如何被连接到相应的需要被同步到事务的资源上(例如,DataSourceTransactionManager对应到JDBC DataSource, HibernateTransactionManager对应到Hibernate的SessionFactory等)。可是,剩下的问题是,直接或间接地使用一种持久化A

  • 问题内容: 我正在使用Android App,无法将View与硬件同步。让我解释。 1)我从线程1的run方法中基于数组A中存储的随机值(即随机睡眠)对Android的麦克风进行静音和取消静音。 2)我画出反映麦克风静音的蓝色脉冲。这是通过独立的View类完成的。 3)通过从倒数计时器的onTick内调用,我在上面视图中绘制的图形上移动了一条红线。 我以这种方式一个接一个地启动两个线程: 线程1.

  • 主要内容:1 什么是Java 线程同步,2 为什么使用Java线程同步,3 Java同步类型,4 Java线程同步的类型,5 线程互斥,6 Java锁的概念,7 线程并发问题引发数据不一致,8 Java synchronized方法的例子1,9 Java synchronized方法的例子21 什么是Java 线程同步 Java中的同步是控制多个线程对任何共享资源的访问的能力。 Java同步是更好的选择,我们希望只允许一个线程访问共享资源。 2 为什么使用Java线程同步 Java线程同步主要用

  • 我有3节课是这样的: 来源Java语言 任务Java语言 主要的Java语言 当类源的x等于4时,只有一个任务继续递增x,直到x等于8,我们恢复正常。结果如下: 要获得此结果,我需要修复什么?

  • 问题内容: 任何人都可以解释以下语句吗……“静态同步方法和非静态同步方法不会互相阻塞-它们可以同时运行” 问题答案: 锁定对象在静态方法和非静态方法上有所不同。静态方法将Class对象用作锁(锁obj:),而非静态方法将实例对象用作锁,此时方法的调用已绑定到该对象(锁obj:)。

  • 我试图更好地理解Java多线程。所以,我知道这句话说只有一个线程可以访问一个对象实例,从而调用该实例的方法(例如,在这种情况下,类 中的减方法。 但是,当你仍然有相同的 会发生什么,但两个线程与不同的 相关联,完全试图调用 的方法?我以为不的消息永远不会被打印出来,但它确实打印出来了。毕竟,仍然只有一个对象实例 ,这是否意味着同步不适用于此示例?