多線程練習一:銀行有一個賬戶,有兩個儲戶分別向同一個賬戶存3000元,每次存1000,存三次,每次存完打印賬戶餘額(兩個儲戶交替存)
對於本題,需要有賬戶(Account)、儲戶(User)、以及一個測試類(AccountTset)
可以分別用繼承Thread類和實現Runnable接口的方式來解決,同時需要注意線程同步的安全問題。
說明:用戶User需要共享一個賬戶Account,這時需要在User類中添加一個Account類型的屬性,以及爲User類提供Account有參構造,以調用其存錢方法,同時在測試類中也可保證不管new 多少個User都是共享同一個Account。
1.繼承Thread類的方法:
class Account {
//賬戶餘額爲money
private double money;
//有參構造器
public Account(double money) {
this.money = money;
}
//存錢方法
public void cunqian(double jine) {
if (jine > 0) {
//用同步代碼塊的方式解決線程安全問題,同步監視器爲Account.class
synchronized (Account.class) {
Account.class.notify();
money += 1000;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "-存款,賬戶餘額爲:" + money);
//
try {
Account.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
class User extends Thread {
private Account account;
//有參構造器
public User(Account account) {
this.account = account;
}
//重寫run方法
@Override
public void run() {
for (int i = 0; i < 3; i++) {
account.cunqian(1000);
}
}
}
public class AccountTest {
public static void main(String[] args) {
Account acc = new Account(0);
//創建兩個User對象 (兩個線程)
User u1 = new User(acc);
User u2 = new User(acc);
//爲兩個對象(線程)命名
u1.setName("甲");
u2.setName("乙");
u1.start();
u2.start();
}
}
2.實現Runnable接口:
說明: ReentrantLock lock = new ReentrantLock(true);在公平鎖(參數爲true)中,線程執行完會讓出cpu執行權給下一個排隊的線程。而非公平鎖(參數爲false或五參數)對鎖的獲取是亂序的。
class Account {
private double money;
實例化ReentrantLock,公平鎖
ReentrantLock lock = new ReentrantLock(true);
public Account(double money) {
this.money = money;
}
public void cunqian(double jine) {
if (jine > 0) {
lock.lock();
money += jine;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "-存款,賬戶餘額爲:" + money);
}
lock.unlock();
}
}
class User implements Runnable {
private Account account;
public User(Account account) {
this.account = account;
}
@Override
public void run() {
for (int i = 0; i < 3; i++) {
account.cunqian(1000);
}
}
}
public class AccountTest {
public static void main(String[] args) {
Account acc = new Account(0);
User user = new User(acc);
Thread t1 = new Thread(user);
Thread t2 = new Thread(user);
t1.setName("甲");
t2.setName("乙");
t1.start();
t2.start();
}
}
趙大海看完能不能發把ju?