Java 一次运行一个线程(而不是并行)
这与我之前提出的问题代码相同,但解决的问题不同。本质上,我试图创建一个具有两个线程的银行帐户,每个线程代表帐户的一个用户。用户将从该账户(随机)存取20美元 但是,这两个线程并行运行,并且提款/存款同时发生。我试图限制这两个线程,使其在执行自己的运行方法之前等待另一个线程完成 下面列出的是代码 线程创建类Java 一次运行一个线程(而不是并行),java,multithreading,Java,Multithreading,这与我之前提出的问题代码相同,但解决的问题不同。本质上,我试图创建一个具有两个线程的银行帐户,每个线程代表帐户的一个用户。用户将从该账户(随机)存取20美元 但是,这两个线程并行运行,并且提款/存款同时发生。我试图限制这两个线程,使其在执行自己的运行方法之前等待另一个线程完成 下面列出的是代码 线程创建类 import java.util.Random; import java.util.concurrent.atomic.AtomicInteger; public class BankAcc
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
public class BankAccount extends Thread{
public static double balance = 1000;
public String threadName;
BankAccount(String name){
threadName = name;
}
public void run(){
System.out.println(threadName + "account initiated.");
for(int i = 0; i < 10; i++){
try{
Random rand = new Random();
int num = rand.nextInt(2) + 1;
if(num == 1){
Thread.sleep(200); //0.2 seconds to deposit
System.out.println(threadName + " is depositing 20$ in the bank.");
balance += 20;
System.out.println("The new balance is " + balance + "dollars" );
}
else{
Thread.sleep(500); //half a second to withdraw
System.out.println(threadName + " is withdrawing 20$ from the bank.");
balance -= 20;
System.out.println("The new balance is " + balance + "dollars.");
}
}
catch(InterruptedException e){
System.out.println("Process terminated.");
}
}
}
}
public class BankAccountSimDriver {
public static void main(String[] args){
Thread user1 = new BankAccountSIm("user1");
Thread user2 = new BankAccountSIm("user2");
user1.start();
user2.start();
}
}
当前的输出:
user1 initiated.
user2 initiated.
user1 is depositing 20$ in the bank.
user2 is depositing 20$ in the bank.
The new balance is 1020.0 dollars
The new balance is 1040.0 dollars
user2 is depositing 20$ in the bank.
The new balance is 1060.0 dollars
user1 is withdrawing 20$ from the bank.
The new balance is 1040.0 dollars.
目前,user1和user2同时运行。我想编辑代码,这样一次只有一个用户可以存款/取款(由sleep()时间间隔表示)
因此,理想的输出:
user1 initiated.
//wait 0.2 seconds
user1 is depositing 20$ in the bank.
The new balance is 1020.0 dollars
user2 initiated.
//wait 0.2 seconds
user2 is depositing 20$ in the bank.
The new balance is 1040.0 dollars
//wait 0.5 seconds
user1 is withdrawing 20$ from the bank.
The new balance is 1020.0 dollars.
...
您需要的是管理对
balance
的并发访问,而不是序列化线程,至少您需要序列化对balance
的访问。有很多方法可以解决这个问题。基本上,您需要一个锁,该锁应该只允许一个线程修改平衡
,另一个线程被阻塞,直到另一个线程释放锁为止
首先,您需要将BanckAccount和它的用户分开
class BankAccount { ... }
class User implements Runnable {
private BankAccount account;
public User(BankAccount account) {
this.account = account;
}
public void run() {
// do something...
}
}
class Test {
public static void main(String []a) {
// One account
BankAccount a = new BankAccount();
// Shared by 2 users
User user1 = new User(a);
User user2 = new User(a);
// Make users behave concurrently
Thread t1 = new Thread(user1);
Thread t2 = new Thread(user2);
t1.start();
t2.start();
// Wait 'til the end of the users activity
t1.join();
t2.join();
}
}
现在,如何管理用户对同一银行帐户的并发访问?通过使BankAccount
方法synchronized
,可以将BankAccount
对象用作隐式锁:
class BankAccount {
private int balance;
public BankAccount(int initialBalance) {
balance = initialBalance;
}
public synchronized int deposit(int amount) {
balance += amount;
return balance;
}
public synchronized int withdraw(int amount) {
balance -= amount;
return balance;
}
}
这样做可以确保标记为synchronized
的方法中不能同时有两个线程,因此两个线程不能同时修改平衡
但是。。。(并发会导致微妙的问题)。。。每个线程可能使用余额的缓存副本,因此通常更适合将该字段标记为volatile
:
private volatile int balance;
请注意,在这种简单的情况下,有些事情可能会被简化,但我试图向您展示问题是什么以及如何解决它们。还要注意,即使是这段代码也可能会导致奇怪的输出,但保证平衡是正确的(现在就挖掘并发性)。如果不希望线程同时运行,为什么要使用线程?您在一个线程中根据随机值进行存款和取款。那么为什么要启动第二个线程user2.start()我使用线程来模拟两个不同的人在一个帐户上执行操作,一次一个。有没有更简单或更有效的替代方案?(正如您所知,Java是新手)不要每次使用Random
实例时都实例化它。这就扼杀了它的“随机”特性。实例化它一次,并让它处理生成新的值。您可以考虑使用java的许多同步机制来围绕代码的关键部分。您是否阅读过关于Java并发编程的教程、书籍或其他培训材料?我猜并不是因为缺少同步和滥用中断异常
。