> 文档中心 > Java多线程练习--取钱

Java多线程练习--取钱

1.需求:
//        小明和小红是一对夫妻,他们有一个共同的账户余额是10万元,模拟2人同时去取钱10万。
//        分析:
//        1:需要提供一个账户类,创建一个账户对象代表2个人的共享账户。
//        2:需要定义一个线程类,线程类可以处理账户对象。
//        3:创建2个线程对象,传入同一个账户对象。
//        4:启动2个线程,去同一个账户对象中取钱10万。

目录

一.同步代码块

二.同步方法

三.lock锁


一.同步代码块

public class Account {    private String cardId;    private double money; // 余额 关键信息    public Account() {    }    public Account(String cardId, double money) { this.cardId = cardId; this.money = money;    }    public String getCardId() { return cardId;    }    public void setCardId(String cardId) { this.cardId = cardId;    }    public double getMoney() { return money;    }    public void setMoney(double money) { this.money = money;    }//    // 100个线程人//    public static void run(){// synchronized (Account.class){//// }//    }    /**     小明 小红     */    public void drawMoney(double money) { // 1、拿到是谁来取钱 String name = Thread.currentThread().getName(); // 同步代码块 // 小明 小红 // this == acc 共享账户 synchronized (this) {     // 2、判断余额是否足够     if(this.money >= money){  // 钱够了  System.out.println(name+"来取钱,吐出:" + money);  // 更新余额  this.money -= money;  System.out.println(name+"取钱后,余额剩余:" + this.money);     }else{  // 3、余额不足  System.out.println(name+"来取钱,余额不足!");     } }    }}public class Account {    private String cardId;    private double money; // 余额 关键信息    public Account() {    }    public Account(String cardId, double money) { this.cardId = cardId; this.money = money;    }    public String getCardId() { return cardId;    }    public void setCardId(String cardId) { this.cardId = cardId;    }    public double getMoney() { return money;    }    public void setMoney(double money) { this.money = money;    }//    // 100个线程人//    public static void run(){// synchronized (Account.class){//// }//    }    /**     小明 小红     */    public void drawMoney(double money) { // 1、拿到是谁来取钱 String name = Thread.currentThread().getName(); // 同步代码块 // 小明 小红 // this == acc 共享账户 synchronized (this) {     // 2、判断余额是否足够     if(this.money >= money){  // 钱够了  System.out.println(name+"来取钱,吐出:" + money);  // 更新余额  this.money -= money;  System.out.println(name+"取钱后,余额剩余:" + this.money);     }else{  // 3、余额不足  System.out.println(name+"来取钱,余额不足!");     } }    }}
public class DrawThread extends Thread{    private Account acc;    public DrawThread(Account acc, String name){ super(name); this.acc = acc;    }    @Override    public void run() { // 小明 小红  : acc acc.drawMoney(100000);    }}

public class TestSafeDemo {    public static void main(String[] args) { // 测试线程安全问题 // 1、创建一个共享的账户对象。 Account acc = new Account("ICBC-111" , 100000); // 2、创建2个线程对象,操作同一个账户对象 new DrawThread(acc, "小明").start(); new DrawThread(acc,"小红").start();    }}

二.同步方法

public class Account {    private String cardId;    private double money; // 余额 关键信息    public Account() {    }    public Account(String cardId, double money) { this.cardId = cardId; this.money = money;    }    public String getCardId() { return cardId;    }    public void setCardId(String cardId) { this.cardId = cardId;    }    public double getMoney() { return money;    }    public void setMoney(double money) { this.money = money;    }    /**      小明 小红this == acc     */    public synchronized void drawMoney(double money) { // 1、拿到是谁来取钱 String name = Thread.currentThread().getName(); // 2、判断余额是否足够 // 小明  小红 if(this.money >= money){     // 钱够了     System.out.println(name+"来取钱,吐出:" + money);     // 更新余额     this.money -= money;     System.out.println(name+"取钱后,余额剩余:" + this.money); }else{     // 3、余额不足     System.out.println(name+"来取钱,余额不足!"); }    }}
public class DrawThread extends Thread{    private Account acc;    public DrawThread(Account acc, String name){ super(name); this.acc = acc;    }    @Override    public void run() { // 小明 小红  : acc acc.drawMoney(100000);    }}
import java.util.*;public class TestSafeDemo {    public static void main(String[] args) { // 测试线程安全问题 // 1、创建一个共享的账户对象。 Account acc = new Account("ICBC-111" , 100000); // 2、创建2个线程对象,操作同一个账户对象 new DrawThread(acc, "小明").start(); new DrawThread(acc,"小红").start();    }}

三.lock锁

import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/**    账户类:余额 , 卡号。 */public class Account {    private String cardId;    private double money; // 余额 关键信息    // final修饰后:锁对象是唯一和不可替换的,非常专业    private final Lock lock = new ReentrantLock();    public Account() {    }    public Account(String cardId, double money) { this.cardId = cardId; this.money = money;    }    public String getCardId() { return cardId;    }    public void setCardId(String cardId) { this.cardId = cardId;    }    public double getMoney() { return money;    }    public void setMoney(double money) { this.money = money;    }    /**      小明 小红     */    public void drawMoney(double money) { // 1、拿到是谁来取钱 String name = Thread.currentThread().getName(); // 2、判断余额是否足够 // 小明  小红 lock.lock(); // 上锁 try {     if(this.money >= money){  // 钱够了  System.out.println(name+"来取钱,吐出:" + money);  // 更新余额  this.money -= money;  System.out.println(name+"取钱后,余额剩余:" + this.money);     }else{  // 3、余额不足  System.out.println(name+"来取钱,余额不足!");     } } finally {     lock.unlock(); // 解锁 }    }}
public class DrawThread extends Thread{    private Account acc;    public DrawThread(Account acc, String name){ super(name); this.acc = acc;    }    @Override    public void run() { // 小明 小红  : acc acc.drawMoney(100000);    }}
public class TestSafeDemo {    public static void main(String[] args) { // 测试线程安全问题 // 1、创建一个共享的账户对象。 Account acc = new Account("ICBC-111" , 100000); // 2、创建2个线程对象,操作同一个账户对象 new DrawThread(acc, "小明").start(); new DrawThread(acc,"小红").start();    }}