问题描述:5个销售买房子,集团只关心销售总量的准确统计数,按照总销售额统计,方便集团公
司给部分发送奖金--------群雄逐鹿起纷争------为了数据安全只能加锁
/**
* 需求:5个销售卖房子,集团只关心销售总量的精确统计数
*/
package com.nanjing.gulimall.zhouyimo.test;
import java.util.Random;
import java.util.concurrent.TimeUnit;
/**
* @author zhou
* @version 1.0
* @date 2024/3/17 9:43 下午
*/
public class ThreadLocalDemo {
public static void main(String[] args) {
House house = new House();
for (int i = 1; i <= 5; i++) {
new Thread(() -> {
int size = new Random().nextInt(5) + 1;
System.out.println(size);
for (int j = 1; j <= size; j++) {
house.saleHouse();
}
}, String.valueOf(i)).start();
}
try {
TimeUnit.MILLISECONDS.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "\t" + "共计卖出多少套: " + house.saleCount);
}
}
class House {
int saleCount = 0;
public synchronized void saleHouse() {
saleCount++;
}
}
4
5
3
4
4
main 共计卖出多少套: 20
需求变更:希望各自分灶吃饭,各凭销售本事提成,按照出单数各自统计-------比如房产中介销售
都有自己的销售额指标,自己专属自己的,不和别人参和。----人手一份天下安
/**
* 需求:需求变更:希望各自分灶吃饭,各凭销售本事提成,按照出单数各自统计-------比如房产中介销售都有自己的销售额指标,自己专属自己的,不和别人参和。
*/
package com.nanjing.gulimall.zhouyimo.test;
import java.util.Random;
import java.util.concurrent.TimeUnit;
/**
* @author zhou
* @version 1.0
* @date 2024/3/17 9:43 下午
*/
public class ThreadLocalDemo {
public static void main(String[] args) {
House house = new House();
for (int i = 1; i <= 5; i++) {
new Thread(() -> {
int size = new Random().nextInt(5) + 1;
for (int j = 1; j <= size; j++) {
house.saleHouse();
house.saleVolumnByThreadLocal();
}
System.out.println(Thread.currentThread().getName() + "\t" + "号销售卖出:" + house.saleVolume.get());
}, String.valueOf(i)).start();
}
try {
TimeUnit.MILLISECONDS.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "\t" + "共计卖出多少套: " + house.saleCount);
}
}
class House {
int saleCount = 0;
public synchronized void saleHouse() {
saleCount++;
}
/*ThreadLocal<Integer> saleVolume = new ThreadLocal<Integer>(){
@Override
protected Integer initialValue() {
return 0;
}
};*/
//上面匿名内部类写的非常繁琐,可以使用ThreadLocal.withInitial()简化
ThreadLocal<Integer> saleVolume = ThreadLocal.withInitial(() -> 0);
public void saleVolumnByThreadLocal() {
int volumn = saleVolume.get();
volumn++;
saleVolume.set(volumn);
}
}
1 号销售卖出:5
2 号销售卖出:5
3 号销售卖出:3
4 号销售卖出:2
5 号销售卖出:4
main 共计卖出多少套: 19
总结
因为每个Thread内有自己的实例副本且该副本只有当前线程自己使用
既然其他ThreadLocal不可访问,那就不存在多线程间共享问题
统一设置初始值,但是每个线程对这个值得修改都是各自线程互相独立得
如何才能不争抢
- 加入synchronized或者Lock控制资源的访问顺序
- 人手一份,大家各自安好,没有必要争抢
改进:
package com.nanjing.gulimall.zhouyimo.test;
import java.util.Random;
import java.util.concurrent.TimeUnit;
/**
* @author zhou
* @version 1.0
* @date 2024/3/17 9:43 下午
*/
public class ThreadLocalDemo {
public static void main(String[] args) {
House house = new House();
for (int i = 1; i <= 5; i++) {
new Thread(() -> {
try {
int size = new Random().nextInt(5) + 1;
for (int j = 1; j <= size; j++) {
house.saleHouse();
house.saleVolumnByThreadLocal();
}
System.out.println(Thread.currentThread().getName() + "\t" + "号销售卖出:" + house.saleVolume.get());
} finally {
house.saleVolume.remove();
}
}, String.valueOf(i)).start();
}
try {
TimeUnit.MILLISECONDS.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "\t" + "共计卖出多少套: " + house.saleCount);
}
}
class House {
int saleCount = 0;
public synchronized void saleHouse() {
saleCount++;
}
/*ThreadLocal<Integer> saleVolume = new ThreadLocal<Integer>(){
@Override
protected Integer initialValue() {
return 0;
}
};*/
//上面匿名内部类写的非常繁琐,可以使用ThreadLocal.withInitial()简化
ThreadLocal<Integer> saleVolume = ThreadLocal.withInitial(() -> 0);
public void saleVolumnByThreadLocal() {
/*int volumn = saleVolume.get();
volumn++;
saleVolume.set(volumn);*/
//或者
saleVolume.set(saleVolume.get() + 1);
}
}