zoukankan      html  css  js  c++  java
  • 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);
                }
    
            }
    
        }
    }
    
    

    运行结果

    这里写图片描述

  • 相关阅读:
    完全背包
    01背包
    游戏编程:为什么C++游戏开发比Java更好,其实是因为这两个点!
    VS code搭建 C 和 C++ 环境的完整图文教程!赶紧收藏,这波不亏!
    来自清华计算机系的招聘信息,第一个要求就劝退99%的人!网友:但福利待遇真好!
    C++ 必看书籍清单!从C++ Primer 到 源码剖析,精通真的很难!
    C语言简单编程速成!保姆级入门教程, 目标达成!
    9 名程序员被抓!这次是真的活该.....
    你知道各类开发语言的薪酬差距吗?高薪在于适合,而不在于广度!
    apache common包 CollectionUtils 使用 详解
  • 原文地址:https://www.cnblogs.com/TCB-Java/p/6797617.html
Copyright © 2011-2022 走看看