demo1:
package com.TestThread;
public class Test {
public static void main(String[] args) {
Account a0 = new Account();
Account a1 = new Account();
User u0 = new User(a0, 2000);
User u1 = new User(a1, 2000);
Thread t0 = new Thread(u0);
Thread t1 = new Thread(u1);
t0.start();
t1.start();
}
}
class Account {
private static int balance = 3000;
/**
* synchronized加在成員方法上只能鎖調用當前方法的對象,例如man方法中如果u0、u1接口構造中傳入的不是同一個Account對象的話,無法使用實現同步鎖。
* 要想所有實例成員共用一個同步鎖可以將該方法修飾爲static
*/
public synchronized void TakeBalance(int m) {
String tname = Thread.currentThread().getName();
System.out.println(tname+"當前餘額"+balance);
if(m < balance) {
System.out.println(tname+"取款2000");
System.out.println(tname+"取款中。。。");
balance -= m;
System.out.println(tname+"取款成功");
System.out.println(tname+"餘額剩餘"+balance);
}else{
System.out.println(tname+"取款失敗,餘額不足");
System.out.println(tname+"餘額剩餘"+balance);
}
}
/**
* 代碼塊同步鎖,synchronized(instance),加在代碼塊前面,傳入的參數爲一個實例對象(或者this),表示對該對象使用同一個鎖。
*
*/
public void TakeBalance2(int m) {
synchronized (this) {
String tname = Thread.currentThread().getName();
System.out.println(tname+"當前餘額"+balance);
if(m < balance) {
System.out.println(tname+"取款2000");
System.out.println(tname+"取款中。。。");
balance -= m;
System.out.println(tname+"取款成功");
System.out.println(tname+"餘額剩餘"+balance);
}else{
System.out.println(tname+"取款失敗,餘額不足");
System.out.println(tname+"餘額剩餘"+balance);
}
}
}
}
class User implements Runnable {
public User(Account a, int m) {
money = m;
account = a;
}
private int money;
private Account account;
@Override
public void run() {
// account.TakeBalance(money);
account.TakeBalance2(money);
}
}
demo2:
package com.TestThread;
/**
* 場景說明:生產者->供應商店,消費者->從商店消費
* 需求說明:商店商品數量最多存放10個,數量少於4個時生產者供應商品;消費者在商品數量大於0時都可以消費,否則等待生產者供應;
*
* 疑惑點:在兩個線程中,當此處while在代碼塊鎖內的時候控制檯輸出規律是一致的,都是 生產滿5個->消費至0->生產滿5個->消費至0...,而目前這樣打印出來是會出現隨機的,即生產完一個就有可能會馬上被消費。
*/
public class Test2 {
public static void main(String[] args) {
Shop shop = new Shop();
new Thread(new Runnable() {//內部類直接實現接口
@Override
public void run() {
while(true) {
synchronized (shop) {
if(shop.productionNum < 5) {
System.out.println("開始生產,當前剩餘商品:"+shop.productionNum);
shop.productionNum++;
System.out.println("生產完成,當前剩餘商品:"+shop.productionNum);
shop.notify();//生產完畢後,喚醒當前正在等候的線程(消費者)
}else{
System.out.println("商品數量充足 暫不生產,當前剩餘商品:"+shop.productionNum);
try {
shop.wait();//當前線程掛起並放棄cpu、同步資源,使別的線程可訪問並修改共享資源,而當前線程等候。
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
},"生產者").start();
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
synchronized (shop) {
if(shop.productionNum > 0) {
System.out.println("開始消費,當前剩餘商品:"+shop.productionNum);
shop.productionNum--;
System.out.println("消費完成,當前剩餘商品:"+shop.productionNum);
shop.notify();//消費完畢後,喚醒當前正在等候的線程(生產者)
}else{
System.out.println("商品數量不足 不能消費,當前剩餘商品:"+shop.productionNum);
try {
shop.wait();//當前線程掛起並放棄cpu、同步資源,使別的線程可訪問並修改共享資源,而當前線程等候。
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
},"消費者").start();
}
}
class Shop {
public static int productionNum = 0;
}