Java之线程同步练习
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之线程同步练习的更多相关文章
- Java 并发 线程同步
Java 并发 线程同步 @author ixenos 同步 1.异步线程本身包含了执行时需要的数据和方法,不需要外部提供的资源和方法,在执行时也不关心与其并发执行的其他线程的状态和行为 2.然而,大 ...
- Java中线程同步的理解 - 其实应该叫做Java线程排队
Java中线程同步的理解 我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread)是一份独立运行的程序,有自己专用的运行栈.线程有可 ...
- java中线程同步的理解(非常通俗易懂)
转载至:https://blog.csdn.net/u012179540/article/details/40685207 Java中线程同步的理解 我们可以在计算机上运行各种计算机软件程序.每一个运 ...
- JAVA中线程同步的方法(7种)汇总
同步的方法: 一.同步方法 即有synchronized关键字修饰的方法. 由于java的每个对象都有一个内置锁,当用此关键字修饰方法时, 内置锁会保护整个方法.在调用该方法前,需要获得内置锁,否则就 ...
- Java多线程——线程同步
在之前,已经学习到了线程的创建和状态控制,但是每个线程之间几乎都没有什么太大的联系.可是有的时候,可能存在多个线程多同一个数据进行操作,这样,可能就会引用各种奇怪的问题.现在就来学习多线程对数据访问的 ...
- Java并发——线程同步Volatile与Synchronized详解
0. 前言 转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52370068 面试时很可能遇到这样一个问题:使用volatile修饰in ...
- Java中线程同步的方法
同步方法 即有synchronized关键字修饰的方法. 由于java的每个对象都有一个内置锁,当用此关键字修饰方法时, 内置锁会保护整个方法.在调用该方法前,需要获得内置锁,否则就处于阻塞状态. 注 ...
- Java中线程同步的理解
我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread)是一份独立运行的程序,有自己专用的运行栈.线程有可能和其他线程共享一些资源, ...
- Java多线程 - 线程同步
多线程操作同一个对象时,容易引发线程安全问题.为了解决线程安全问题,Java多线程引入了同步监视器. 同步代码块 同步代码块语法格式如下: synchronized(obj){ //此处的代码即为同步 ...
- JAVA多线程线程同步问题
线程同步 在多线程的编程环境下,可能看着没有问题的代码在运行几千上万或者更多次后,出现了一些看着很奇怪的问题,出现这样的问题的原因就是可能会有两个或者更多个线程进入了同一块业务处理代码中导致了判断失效 ...
随机推荐
- linux c socket 并发 服务端
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types. ...
- 【外文翻译】 为什么我要写 getters 和setters
原文作者: Shamik Mitra 原文链接:https://dzone.com/articles/why-should-i-write-getters-and-setters 当我开始我的java ...
- Array和ArrayCollection作为数据源的一个应用区别
在不用[Enabled]元标签的前提下,将一个Array赋值给DataGrid.DataList等控件的DataProvider后,当Array值发生改变时,控件显示内容不会及时更新(可调用控件的in ...
- javaweb项目-医者天下 (Spring+SpringMVC+MyBatis)
项目下载地址:http://download.csdn.net/detail/qq_33599520/9826683 项目完整结构图: 项目简介: 医者天下项目是一个基于Spring+SpringMV ...
- 篇2 安卓app自动化测试-初识python调用appium
篇2 安卓app自动化测试-初识python调用appium --lamecho辣么丑 1.1概要 大家好!我是lamecho(辣么丑),上一篇也是<安卓app自动化测 ...
- 探讨数据进行AES加密和解密以及.NET Core对加密和解密为我们提供了什么?
前言 对于数据加密和解密每次我都是从网上拷贝一份,无需有太多了解,由于在.net core中对加密和解密目前全部是统一了接口,只是做具体的实现,由于遇到过问题,所以将打算基本了解下其原理,知其然足矣, ...
- Display:table;妙用,使得左右元素高度相同
我们在设计网页的时候,为了左右能够分明一点,我们经常会在左边元素弄一个border-right,但是出现一个问题,如果左边高度比较小,这根线就短了,下面空了一部分,反正如果在右边的元素弄一个borde ...
- Oracle学习历程--创建用户,分配表空间
记录下学习Oracle12c的过程中的点点滴滴. Oracle12c新特性:http://www.cnblogs.com/kerrycode/p/3386917.html --创建临时表空间CREAT ...
- 蓝桥杯-密码发生器-java
/* (程序头部注释开始) * 程序的版权和版本声明部分 * Copyright (c) 2016, 广州科技贸易职业学院信息工程系学生 * All rights reserved. * 文件名称: ...
- 优化UI控件 【译】
翻译自:https://unity3d.com/cn/learn/tutorials/topics/best-practices/optimizing-ui-controls?playlist=300 ...