下面是针对Java多线程实现取款小程序的完整攻略。
准备工作
在开始之前,我们需要先了解一些Java多线程方面的基础知识,如线程创建与启动、线程同步、线程通信等。这些知识我们可以通过阅读相关的书籍或者在线教程来学习掌握。
实现步骤
- 创建一个银行账户类,包括账户余额、账户号码等属性,以及存、取款等方法。
public class Account {
private String accountNo;//账户号码
private double balance;//账户余额
//省略构造方法、setter和getter方法
//存款操作
public synchronized void deposit(double money) {
balance += money;
System.out.println(Thread.currentThread().getName() + " 存款 " + money + " 成功,账户余额为:" + balance);
}
//取款操作
public synchronized void withdraw(double money) {
if (balance >= money) {
balance -= money;
System.out.println(Thread.currentThread().getName() + " 取款 " + money + " 成功,账户余额为:" + balance);
} else {
System.out.println(Thread.currentThread().getName() + " 取款 " + money + " 失败,余额不足!");
}
}
}
在存款和取款操作中,我们使用了synchronized关键字来实现同步,在执行存款或取款操作时,需要对当前的账户对象进行加锁,保证同一时间只有一个线程能够对该账户进行操作。
- 创建多个线程进行取款和存款操作。为了更好地展现账户余额的变化,我们可以设置取款和存款线程具有不同的优先级。
public static void main(String[] args){
Account account = new Account("001", 1000);
Thread depositThread1 = new Thread(new DepositThread(account), "存款线程1");
Thread depositThread2 = new Thread(new DepositThread(account), "存款线程2");
Thread withdrawThread1 = new Thread(new WithdrawThread(account), "取款线程1");
Thread withdrawThread2 = new Thread(new WithdrawThread(account), "取款线程2");
depositThread1.setPriority(Thread.MAX_PRIORITY);
depositThread2.setPriority(Thread.MAX_PRIORITY);
withdrawThread1.setPriority(Thread.MIN_PRIORITY);
withdrawThread2.setPriority(Thread.MIN_PRIORITY);
depositThread1.start();
depositThread2.start();
withdrawThread1.start();
withdrawThread2.start();
}
//存款线程
class DepositThread implements Runnable{
private Account account;
public DepositThread(Account account) {
this.account = account;
}
@Override
public void run() {
for(int i=0;i<100;i++){
account.deposit(10);
}
}
}
//取款线程
class WithdrawThread implements Runnable{
private Account account;
public WithdrawThread(Account account) {
this.account = account;
}
@Override
public void run() {
for(int i=0;i<100;i++){
account.withdraw(10);
}
}
}
运行程序后,我们可以看到如下结果:
存款线程1 存款 10.0 成功,账户余额为:1010.0
取款线程1 取款 10.0 成功,账户余额为:1000.0
存款线程1 存款 10.0 成功,账户余额为:1010.0
取款线程2 取款 10.0 成功,账户余额为:1000.0
存款线程1 存款 10.0 成功,账户余额为:1010.0
...
我们可以看到,存款和取款操作依次进行,余额也在正常变化。
- 添加取款上限,避免账户余额小于0的情况发生。如果账户余额小于0,则将当前线程阻塞,直到其他线程存款为止。
public synchronized void withdraw(double money) {
if (balance >= money) {
balance -= money;
System.out.println(Thread.currentThread().getName() + " 取款 " + money + " 成功,账户余额为:" + balance);
} else {
System.out.println(Thread.currentThread().getName() + " 取款 " + money + " 失败,余额不足!");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void deposit(double money) {
balance += money;
System.out.println(Thread.currentThread().getName() + " 存款 " + money + " 成功,账户余额为:" + balance);
notifyAll();
}
在取款操作中,如果发现账户余额不足,则使用wait()将当前线程阻塞,等待其他线程进行存款操作。在存款操作中,我们使用notifyAll()方法来唤醒之前被阻塞的线程,让它们继续执行。这种方式可以避免账户余额小于0的情况发生。
- 实现一个定时器,每隔一段时间自动进行存款操作。例如,我们可以设置每隔10秒钟,自动向账户存入100元。
class AutoDepositTask extends TimerTask {
private Account account;
public AutoDepositTask(Account account) {
this.account = account;
}
@Override
public void run() {
account.deposit(100);
}
}
public static void main(String[] args){
Account account = new Account("001", 1000);
Timer timer = new Timer();
timer.schedule(new AutoDepositTask(account), 0, 10000);
...
}
我们创建了一个AutoDepositTask类,继承了TimerTask类,并重写了其中的run()方法,用于执行自动存款的操作。在main()方法中,创建了一个Timer对象,并使用schedule()方法设置了定时任务的执行方式。
示例说明
- 多个线程同时对同一个账户进行存款和取款操作。由于在存款和取款操作中实现了同步,各线程对账户进行的操作互不干扰,保证了线程安全。
- 当余额不足时,取款线程被阻塞。在使用wait()方法将当前线程阻塞时,我们还需要进行异常处理,以保证程序的健壮性。同时,在存款线程中使用notifyAll()唤醒线程时,需要使用同步方法或同步代码块来保证线程安全。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java多线程实现取款小程序 - Python技术站