卖票
package org.example.concurrency.test;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
/**
* @author huskyui
*/
@Slf4j
public class ExerciseSell {
public static void main(String[] args) {
TicketWindow window = new TicketWindow(10000);
//
List<Integer> amountList = new Vector<>();
List<Thread> threadList = new ArrayList<>();
for (int i = 0;i<2000;i++){
Thread thread = new Thread(()->{
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
int amount = window.sell(1);
amountList.add(amount);
});
threadList.add(thread);
thread.start();
}
threadList.forEach(t-> {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
log.info("余票:{}",window.getCount());
int count = 0;
for (int amount : amountList){
count+=amount;
}
log.info(" 余票2 : {}",count);
}
}
class TicketWindow{
private int count;
public TicketWindow(int count){
this.count = count;
}
public int getCount(){
return count;
}
// public synchronized int sell(int amount){
// if(this.count >= amount){
// this.count -=amount;
// return amount;
// }else{
// return 0;
// }
// }
public int sell(int amount){
synchronized (this) {
if (this.count >= amount) {
this.count -= amount;
return amount;
} else {
return 0;
}
}
}
}
我们可以看到,多个线程对一个对象进行竞争访问的时候,我们加入 关键字 synchronized
就可以锁定 当前创建的 TicketWindow window = new TicketWindow(10000);
转账
package org.example.concurrency.test;
import lombok.extern.slf4j.Slf4j;
import java.util.Random;
/**
* @author huskyui
*/
@Slf4j
public class ExerciseTransfer {
public static void main(String[] args) throws InterruptedException {
Account account1 = new Account(1000);
Account account2 = new Account(1000);
Thread t1 = new Thread(() -> {
for (int i = 0; i < 100; i++) {
account1.transfer(account2, randomAmount());
}
}, "t1");
Thread t2 = new Thread(() -> {
for (int i = 0; i < 100; i++) {
account2.transfer(account1, randomAmount());
}
}, "t2");
t1.start();
t2.start();
t1.join();
t2.join();
log.info("余额 {}", account1.getMoney() + account2.getMoney());
}
// random 为线程安全
static Random random = new Random();
public static int randomAmount() {
return random.nextInt(100) + 1;
}
}
class Account {
private int money;
public Account(int money) {
this.money = money;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
public void transfer(Account target, int amount) {
synchronized (Account.class) {
if (this.money >= amount) {
this.setMoney(this.getMoney() - amount);
target.setMoney(target.getMoney() + amount);
}
}
}
}
我们可以转账时,我们需要同时给两个account对象加锁,我们如果还是想之前的方式,进行加锁就会出现问题
public synchronized void transfer(Account target, int amount) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (this.money >= amount) {
this.setMoney(this.getMoney() - amount);
System.out.println(target.getMoney());
target.setMoney(target.getMoney() + amount);
}
}
所以我们可以锁住Account.class这个类。但是这个效率低。