系列的几篇文章介绍一下Java语言的多线程的使用。
已经实现了一个账户(Account) ,可以供多个线程同时进行取钱和存钱的操作。
本次将定义一个差不多的账户类,但是本次的这个账号在多个线程同时操作会带来线程安全的问题。
将账户类修改为下面的形式
class AccountUnsafe {
int balence = 500;
void withdraw(final int amount) throws InterruptedException {
while (this.balence < amount) {
System.out.println("线程 " + Thread.currentThread().getName() + "在尝试取钱 ");
System.out.println("尝试取钱 " + amount + ", 余额为 " + this.balence+"无法取钱");
Thread.sleep(100);
}
this.balence -= amount;
System.out.println("取钱 " + amount + ", 余额为 " + this.balence);
}
void deposit(final int amount) throws InterruptedException {
while (this.balence >= 500) {
System.out.println("线程 " + Thread.currentThread().getName() + "在尝试存钱 ");
System.out.println("尝试存钱 " + amount + ", 余额为 " + this.balence+"无法取钱");
Thread.sleep(100);
}
this.balence += amount;
System.out.println("存钱 " + amount + ", 余额为 " + this.balence);
}
}
同样,开始余额为500。
定义一个取钱方法withdraw,每次取500出来,如果余额不足则不会取钱。
定义一个存钱方法deposit,每次存100元,如果余额大于等于500则不会存钱。
注意,这次withdraw和deposit并不是同步(synchronized)的。
如果余额不满足条件,则该线程睡眠100毫秒,以给其他线程以执行的机会,否则可能某一个线程一直在取钱。其它线程无机会执行。
取钱的线程和存钱的线程与之前定义一样
Runnable withdraw = new Runnable() {
@Override
public void run() {
try {
while (true) {
accountUnsafe.withdraw(500);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Runnable deposit = new Runnable() {
@Override
public void run() {
while (true) {
try {
accountUnsafe.deposit(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
每当启动一个线程进行取钱,则该线程会一直取钱。
每当启动一个线程存钱,则该线程一直存钱。
完整代码如下:
package com.basic.thread;
public class ThreadTest2 {
AccountUnsafe accountUnsafe = new AccountUnsafe();// 线程不安全的账户
public static void main(String[] args) {
new ThreadTest2().accountTest();
}
class AccountUnsafe {
int balence = 500;
void withdraw(final int amount) throws InterruptedException {
while (this.balence < amount) {
System.out.println("线程 " + Thread.currentThread().getName() + "在尝试取钱 ");
System.out.println("尝试取钱 " + amount + ", 余额为 " + this.balence);
Thread.sleep(100);
}
this.balence -= amount;
System.out.println("取钱 " + amount + ", 余额为 " + this.balence+"无法取钱");
}
void deposit(final int amount) throws InterruptedException {
while (this.balence >= 500) {
System.out.println("线程 " + Thread.currentThread().getName() + "在尝试存钱 ");
System.out.println("尝试存钱 " + amount + ", 余额为 " + this.balence+"无法取钱");
Thread.sleep(100);
}
this.balence += amount;
System.out.println("存钱 " + amount + ", 余额为 " + this.balence);
}
}
Runnable withdraw = new Runnable() {
@Override
public void run() {
try {
while (true) {
accountUnsafe.withdraw(500);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Runnable deposit = new Runnable() {
@Override
public void run() {
while (true) {
try {
accountUnsafe.deposit(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
void accountTest() {
Thread t1 = new Thread(this.withdraw);
Thread t11 = new Thread(this.withdraw);
Thread t12 = new Thread(this.withdraw);
Thread t13 = new Thread(this.withdraw);
Thread t14 = new Thread(this.withdraw);
Thread t2 = new Thread(this.deposit);
Thread t21 = new Thread(this.deposit);
Thread t22 = new Thread(this.deposit);
Thread t23 = new Thread(this.deposit);
Thread t24 = new Thread(this.deposit);
t1.start();
t11.start();
t12.start();
t13.start();
t14.start();
t2.start();
t21.start();
t22.start();
t23.start();
t24.start();
}
}
运行程序,查看控制台输出:
//省略以上部分
线程 Thread-0在尝试取钱
尝试取钱 500, 余额为 400无法取钱
存钱 100, 余额为 400
存钱 100, 余额为 300
存钱 100, 余额为 300
线程 Thread-6在尝试存钱
存钱 100, 余额为 300
线程 Thread-9在尝试存钱
尝试存钱 100, 余额为 500无法取钱
线程 Thread-1在尝试取钱
尝试取钱 500, 余额为 500无法取钱
存钱 100, 余额为 300
线程 Thread-7在尝试存钱
尝试存钱 100, 余额为 500无法取钱
尝试存钱 100, 余额为 500无法取钱
//省略以下部分
可以看到,出现了连续存钱100但是账户余额均为300的现象。
出现了账户金额不正常的现象。