在该示例代码中,TestAccount类是测试类,主要实现创建帐户Account类的对象,以及启动学生线程StudentThread和启动家长线程GenearchThread。在StudentThread线程中,执行的功能是每隔2秒中取一次钱,每次取50元。在GenearchThread线程中,执行的功能是每隔12秒存一次钱,每次存200。这样存款和取款之间不仅时间间隔存在差异,而且数量上也会出现交叉。而该示例中,最核心的代码是Account类的实现。

在Account类中,实现了同步控制功能,在该类中包含一个关键的属性money,该属性的作用是存储帐户金额。在介绍该类的实现前,首先介绍一下两个同步方法——wait和notify方法的使用,这两个方法都是Object类中的方法,也就是说每个类都包含这两个方法,换句话说,就是Java天生就支持同步处理。这两个方法都只能在synchronized修饰的方法或语句块内部采用被调用。其中wait方法的作用是使调用该方法的线程休眠,也就是使该线程退出CPU的等待队列,处于冬眠状态,不执行动作,也不占用CPU排队的时间,notify方法的作用是唤醒一个任意该对象的线程,该线程当前处于休眠状态,至于唤醒的具体是那个则不保证。在Account类中,被StudentThread调用的getMoney方法的功能是判断当前金额是否是0,如果是则使StudentThread线程处于休眠状态,如果金额不是0,则取出50元,同时唤醒使用该帐户对象的其它一个线程,而被GenearchThread线程调用的saveMoney方法的功能是判断当前是否不为0,如果是则使GenearchThread线程处于休眠状态,如果金额是0,则存入200元,同时唤醒使用该帐户对象的其它一个线程。

如果还是不清楚,那就结合前面的程序执行结果来解释一下程序执行的过程:在程序开始执行时,学生线程和家长线程都启动起来,所以输出“准备取钱”和“准备存钱”,然后学生线程按照该线程run方法的逻辑执行,先延迟2秒,然后调用帐户对象a中的getMoney方法,但是由于初始情况下帐户对象a中的money数值为0,所以学生线程就休眠了。在学生线程执行的同时,家长线程也按照该线程的run方法的逻辑执行,先延迟12秒,然后调用帐户对象a中的saveMoney方法,由于帐户a对象中的money为零,条件不成立,所以执行存入200元,同时唤醒线程,由于使用对象a的线程现在只有学生线程,所以学生线程被唤醒,开始执行逻辑,取出50元,然后唤醒线程,由于当前没有线程处于休眠状态,所以没有线程被唤醒。同时家长线程继续执行,先延迟12秒,这个时候学生线程执行了4次,耗时4X2秒=8秒,就取光了帐户中的钱,接着由于帐户为0则学生线程又休眠了,一直到家长线程延迟12秒结束以后,判断帐户为0,又存入了200元,程序继续执行下去。

在解决多线程问题是,互斥和同步都是解决问题的思路,如果需要形象的比较这两种方式的区别的话,就看一下下面的示例。一个比较忙的老总,桌子上有2部电话,在一部处于通话状态时,另一部响了,老总拿其这部电话说我在接电话,你等一下,而没有挂电话,这种处理的方式就是互斥。而如果老总拿其另一部电话说,我在接电话,等会我打给你,然后挂了电话,这种处理的方式就是同步。两者相比,互斥明显占用系统资源(浪费电话费,浪费别人的时间),而同步则是一种更加好的解决问题的思路。

JAVA多线程----用--取钱问题2的更多相关文章

  1. JAVA多线程----用--取钱问题1

    “生产者-消费者”模型,也就是生产者线程只负责生产,消费者线程只负责消费,在消费者发现无内容可消费时则睡觉.下面举一个比较实际的例子——生活费问题. 生 活费问题是这样的:学生每月都需要生活费,家长一 ...

  2. Java多线程---同步与锁

    一,线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏. 二.同步和锁定 1.锁的原理 Java中每个对象都有一个内置锁. 当程序运行到非静态的synchronized同步方法上时,自动 ...

  3. Java多线程之使用ATM与柜台对同一账户取钱

    钱数要设置成静态的变量,两种取钱方式操作的是同一个银行账户! 废话不多说,直接上代码.注释写的都很详细!!! package com.thread.multi2; public class Bank ...

  4. 【JAVA】编程(3)---王狗蛋先生去取钱,发现余额不足 !?!?

    作业要求: 1.写一个名为Account的类模拟账户.该类的属性和方法如下所示: 该类包括的属性: ID,余额balance,年利率; 包含的方法:各属性的set和get方法.取款方法withdraw ...

  5. Java多线程 3 线程同步

    在之前,已经学习到了线程的创建和状态控制,但是每个线程之间几乎都没有什么太大的联系.可是有的时候,可能存在多个线程多同一个数据进行操作,这样,可能就会引用各种奇怪的问题.现在就来学习多线程对数据访问的 ...

  6. Java—多线程编程

    一个多线程程序包含两个或多个能并发运行的部分.程序的每一部分都称作一个线程,并且每个线程定义了一个独立的执行路径. 进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程.一个线程不能独立的存 ...

  7. java多线程基础

    多线程基础 读书练习照猫画虎 package Threadtest; import java.util.Date; import java.util.concurrent.ArrayBlockingQ ...

  8. Java总结篇系列:Java多线程(三)

    本文主要接着前面多线程的两篇文章总结Java多线程中的线程安全问题. 一.一个典型的Java线程安全例子 public class ThreadTest { public static void ma ...

  9. JAVA多线程的问题以及处理【转】

    http://www.cnblogs.com/springcsc/archive/2009/12/03/1616394.html 12.4 多线程问题及处理          多线程编程为程序开发带来 ...

随机推荐

  1. [转][修]利用matlab绘制地图上的点、线、面

    一.绘制点 %生成背景地图地图   h = worldmap('France'); %读取和显示大陆架   landareas = shaperead('landareas.shp','UseGeoC ...

  2. pt-table-sync修复mysql主从不一致的数据

    pt-table-sync简介 顾名思义,它用来修复多个实例之间数据的不一致.它可以让主从的数据修复到最终一致,也可以使通过应用双写或多写的多个不相关的数据库实例修复到一致.同时它还内部集成了pt-t ...

  3. db2 函数、存储过程示例

    1.函数 --drop function getMaxDate; create FUNCTION getMaxDate (y int, m int ) returns date begin DECLA ...

  4. geoserver源码学习与扩展——增加服务接口

    参看:http://www.cnblogs.com/sillyemperor/archive/2011/01/11/1929420.html 上文写的很详细了.

  5. 在ajax请求下的缓存机制

    1.在服务端加 header(“Cache-Control: no-cache, must-revalidate”);2.在ajax发送请求前加上 anyAjaxObj.setRequestHeade ...

  6. 我的Ansible学习笔记

    Ansible常见错误 http://afewbug.com/article/26官方文档 http://docs.ansible.com/ansible/安装配置 http://sofar.blog ...

  7. PHP 数组遍历 foreach 语法结构

    foreach 语法结构用于遍历数组. foreach() PHP foreach() 语法结构用于遍历操作或输出数组,foreach() 仅能用于遍历数组或对象,当试图将其用于其它数据类型或者一个未 ...

  8. Warsaw U Contest Petrozavo dsk Summer 2011 Training Camp, Monday, September 5, 2011

    Warsaw U Contest Petrozavo dsk Summer 2011 Training Camp, Monday, September 5, 2011 Problem A.Chocol ...

  9. python的os.urandom 的用途

    Python中os.urandom(n)的作用 随机产生n个字节(0-255)的字符串,可以作为随机加密key使用~ >>> index = os.urandom(2) >&g ...

  10. HTML DOM(二):节点的增删改查

    上一篇讲述了DOM的基本知识,从其得知,在DOM眼中,HTML的每个成分都可以看作是节点(文档节点.元素节点.文本节点.属性节点.注释节点,其中,属性节点是属于元素节点),本篇的内容就是通过DOM对这 ...