1.有一张银行卡:*属性:name,money(账户余额)*

多线程操作同一张银行卡:

金额:x(每次存钱取钱的数额,取钱时x为负数,存钱时x为整数)

定义一个add方法:用于存取钱,参数为x,即每次取或存的金额

add(int x){

判断x的正负

要么存,要么取

显示余额

}

多线程实现可以存钱也可以取钱,保证线程的安全.

分析:

线程安全是指保证进入执行状态的线程能将当次行为执行完成,即实现同步

金额是后台输入的,或直接使用随机数解决

代码:

方法一:直接操作,以及后台输入金额

package Homework;

import java.util.Scanner;

public class Test1 {
public static void main(String[] args) {
Card card=new Card("中国银行卡",0);
MyThread thread=new MyThread(card);
MyThread thread2=new MyThread(card);
MyThread thread3=new MyThread(card);
thread.start();
thread2.start();
thread3.start();
}
}
//银行卡类
class Card{
private String name;
private int money;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
@Override
public String toString() {
return "Card [name=" + name + ", money=" + money + "]";
}
public Card(String name, int money) {
super();
this.name = name;
this.money = money;
}
public Card() {
super();
} //定义的add方法,操作账户进行存取钱
public synchronized void add(int num){
int money1=getMoney();
setMoney(money1+num);
if(num>0){
System.out.println(Thread.currentThread().getName()+"【存】了"+num+"元,当前"+getName()+"余额为:"+getMoney());
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
System.out.println(Thread.currentThread().getName()+"【取】了"+(-num)+"元,当前"+getName()+"余额为:"+getMoney());
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} //线程
class MyThread extends Thread{
Card card;
public MyThread(Card card){
this.card=card;
}
@Override
public void run() {
Scanner input=new Scanner(System.in);
while(true){
synchronized (card) {
System.out.println("请输入金额:");
int num=input.nextInt();
card.add(num);
}
}
}
}

运行结果:

方法二:使用标志位,以及随机数

银行卡类:

package com.qf.demo;

public class Card1 {

    private int money = 0;

    boolean flag = true; //true 取了钱,但是还没存     取钱的等着   存钱的执行
// false 存了钱了,但是没取 存钱的等着 取钱的执行
public Card1(int money) {
super();
this.money = money;
} public Card1() {
super();
} public int getMoney() {
return money;
} public void setMoney(int money) {
this.money = money;
} @Override
public String toString() {
return "Card1 [money=" + money + "]";
} public synchronized void save(){
if(flag == false){// 存了还没取 存钱等着
try {
this.wait();// 挂起来的是 存钱的线程
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} // 就证明是true 取了还没存
this.money+=1000;
System.out.println("存了1000,还剩下"+this.money);
// 已经存完钱了
flag = false;
this.notify();
} public synchronized void get(){
if(flag==true){// true 取了还没存 取钱的等着 存钱的 执行
try {
this.wait();// 挂起来的是取钱的线程
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 没进去wait 就证明flag 是false 存了还没取
this.money = this.money-1000;
System.out.println("取了1000,还剩"+this.money);
// 取完钱了
flag = true;
this.notify();
}
}

测试类与子线程:

package com.qf.demo;

public class Test {

    public static void main(String[] args) {
Card card = new Card();
MyThread thread = new MyThread(card);
MyThread thread2 = new MyThread(card); thread.start();
thread2.start(); }
} class Card{
private String name;
private int money ;
public Card(String name, int money) {
super();
this.name = name;
this.money = money;
}
public Card() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
@Override
public String toString() {
return "Card [name=" + name + ", money=" + money + "]";
}
// 最小作用域最强原则: 局部变量和 全局变变量同名的时候,在这个方法中优先使用的是 局部变量
public void add(int money){
if(money>0){
this.money = this.money+money;
System.out.println(Thread.currentThread().getName()+"存了"+money+"余额为"+this.money);
}else {
this.money = this.money+money;
System.out.println(Thread.currentThread().getName()+"取了"+(-money)+"余额为"+this.money);
}
}
} class MyThread extends Thread{
Card card; public MyThread(Card card) {
this.card = card;
} @Override
public void run() {
// -499~500
for (int i = 0; i < 20; i++) {
synchronized (card) {
int a = (int)(Math.random()*1000+1)-500;
card.add(a);
} } }
}

运行结果

Java之线程同步练习的更多相关文章

  1. Java 并发 线程同步

    Java 并发 线程同步 @author ixenos 同步 1.异步线程本身包含了执行时需要的数据和方法,不需要外部提供的资源和方法,在执行时也不关心与其并发执行的其他线程的状态和行为 2.然而,大 ...

  2. Java中线程同步的理解 - 其实应该叫做Java线程排队

    Java中线程同步的理解 我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread)是一份独立运行的程序,有自己专用的运行栈.线程有可 ...

  3. java中线程同步的理解(非常通俗易懂)

    转载至:https://blog.csdn.net/u012179540/article/details/40685207 Java中线程同步的理解 我们可以在计算机上运行各种计算机软件程序.每一个运 ...

  4. JAVA中线程同步的方法(7种)汇总

    同步的方法: 一.同步方法 即有synchronized关键字修饰的方法. 由于java的每个对象都有一个内置锁,当用此关键字修饰方法时, 内置锁会保护整个方法.在调用该方法前,需要获得内置锁,否则就 ...

  5. Java多线程——线程同步

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

  6. Java并发——线程同步Volatile与Synchronized详解

    0. 前言 转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52370068 面试时很可能遇到这样一个问题:使用volatile修饰in ...

  7. Java中线程同步的方法

    同步方法 即有synchronized关键字修饰的方法. 由于java的每个对象都有一个内置锁,当用此关键字修饰方法时, 内置锁会保护整个方法.在调用该方法前,需要获得内置锁,否则就处于阻塞状态. 注 ...

  8. Java中线程同步的理解

    我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread)是一份独立运行的程序,有自己专用的运行栈.线程有可能和其他线程共享一些资源, ...

  9. Java多线程 - 线程同步

    多线程操作同一个对象时,容易引发线程安全问题.为了解决线程安全问题,Java多线程引入了同步监视器. 同步代码块 同步代码块语法格式如下: synchronized(obj){ //此处的代码即为同步 ...

  10. JAVA多线程线程同步问题

    线程同步 在多线程的编程环境下,可能看着没有问题的代码在运行几千上万或者更多次后,出现了一些看着很奇怪的问题,出现这样的问题的原因就是可能会有两个或者更多个线程进入了同一块业务处理代码中导致了判断失效 ...

随机推荐

  1. vue2 与后台信息交互

    vue-resource  是vue的ajax请求插件 vue-resource文档:https://github.com/vuejs/vue-resource/blob/master/docs/ht ...

  2. Eclipse默认编码设置

    eclipse 默认编码居然是GBK,js文件默认编码是ISO-....怎么可以这样呢?都修改成UTF8的方法:1.windows->Preferences...打开"首选项" ...

  3. finally块执行时间

    finally块在代码中什么时候被执行? 在Java语言的异常处理中,finally块的作用十九为了保证无论出现什么情况,finally块里面的代码一定会被执行.由于程序执行return就以为这结束对 ...

  4. MySQL 5.7贴心参数之 log_timestamps

    写在前面 使用 MySQL 的过程中,经常会有人碰到这么一个问题,看错误日志.慢查询日志的时候,时间总是和本地时间对不上,差了 8 个小时,这样分析起来就相对麻烦了一些. 新改进 对于不知道是什么原因 ...

  5. 111_climbing-stairs

    /*@Copyright:LintCode@Author:   Monster__li@Problem:  http://www.lintcode.com/problem/climbing-stair ...

  6. 我使用的Chrome插件列表

    AdBlock 用来屏蔽广告的,有一些网站会探测出你在使用AdBlock.如果一定要继续浏览的话,你可能需要暂停一下AdBlock Vimium 非常推荐喜欢vim的用户试试看这款插件,它的主要特色是 ...

  7. JavaScript动画1-速度动画

    动画实际上就是在一定时间内,改变一个元素的某些属性. 这里简单实现一个JavaScript运动的框架.主要包括: 速度动画(改变left.right.width.height.opacity) 缓冲运 ...

  8. Activiti引擎启动失败

    今天部署项目测试时发现activiti启动失败,研究了会才把问题解决!! 错误信息:SEVERE: problem during schema create, statement create seq ...

  9. Oracle GoldenGate中HANDLECOLLISIONS参数使用详解

    Oracle GoldenGate中HANDLECOLLISIONS参数使用详解   HANDLECOLLISIONS 是一个 replicat 进程参数,主要在 initial load 中使用.在 ...

  10. 关于MAC设置免费的动态壁纸

    首先大部分的动态壁纸都是收费的或者是已经固定的,其实这一款也是固定的 但是这个固定的是可以进行修改的 第一先在App Store下载 LiveDesktop Pro  这一款是免费的 然后下载后进行打 ...