开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第29天,点击查看活动详情
初识并发问题
场景:买票 多线程抢一些票
package com.wyh.thread;
/**
* @program: Thread
* @description: 火车票抢票
* @author: 魏一鹤
* @createDate: 2021-12-25 00:18
**/
//发现问题 多个线程操作同一个资源的情况下 线程不安全了 数据混乱
public class TestThread3 implements Runnable {
//票数
int ticketNums=10;
@Override
public void run() {
//火车票抢票
while (true) {
//如果没票了就停止
if(ticketNums<=0){
break;
}
//模拟延迟
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
//Thread.currentThread().getName() 获取当前线程名称 我们是可以给线程命名的
System.out.println(Thread.currentThread().getName() + "-->抢到了" +ticketNums--+ "张票" );
}
}
public static void main(String[] args){
//创建runnable接口的实现类对象
TestThread3 testThread3 = new TestThread3();
//3个线程一起去抢票
new Thread(testThread3, "线程1" ).start();
new Thread(testThread3, "线程2" ).start();
new Thread(testThread3, "线程3" ).start();
}
}
运行后发现 多个线程操作同一个资源的情况下 线程不安全了 数据混乱
场景 :龟兔赛跑 首先来个赛跑距离 然后要距离离终点越来越近判断比赛是否结束,兔子需要睡觉,我们模拟兔子睡觉,让兔子的线程休眠,最终让乌龟胜利
package com.wyh.thread;
/**
* @program: Thread
* @description: 龟兔赛跑
* @author: 魏一鹤
* @createDate: 2021-12-25 23:47
**/
public class TestThread4 implements Runnable{
//胜利者
private String winner;
// 线程代码
@Override
public void run() {
//终点为100
for (int i = 0; i <= 100; i++) {
//模拟兔子休息 如果线程名字是兔子,就让它睡觉 每十步也让兔子睡觉
if(Thread.currentThread().getName().equals( "兔子" )){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
boolean flag = gameOver(i);
//如果比赛结束,就停止程序
if(flag){
break;
}
//打印线程名称
System.out.println(Thread.currentThread().getName() + "跑了" +i+ "步" );
}
}
//判断是否完成比赛
public boolean gameOver(int steps) {
//判断是否有胜利者 如果有胜利者游戏结束
if(winner!=null){
return true;
}{ //如果步数为100 游戏结束
if (steps>=100){
//如果步数为100 把这个线程定义为胜利者
winner=Thread.currentThread().getName();
System.out.println( "winner是:" +winner);
return true;
}
}
return false;
}
public static void main(String[] args){
//主程序
//定义赛道
TestThread4 race=new TestThread4();
//双线程开始跑步
new Thread(race, "兔子" ).start();
new Thread(race, "乌龟" ).start();
}
}
静态代理
代理(我帮你做一些事情),有静态代理就有动态代理,今天学习静态代理,动态代理以后再学习
例子 我结婚,我是一个真实的对象,婚庆公司帮我拍摄布置等,帮我代理(代理我),我和婚庆公司都去实现结婚接口即可,我只需要做我的是,其他事情婚庆公司(代理)帮我做即可
package com.wyh.thread;
/**
* @program: Thread
* @description: 静态代理
* @author: 魏一鹤
* @createDate: 2021-12-29 21:48
**/
//静态代理模式总结
//1 真实对象和代理对象都要实现同一个接口
//2 代理对象要代理真实的角色
//好处
// 1 代理对象可以做很多真实对象做不了的事情
// 2 真实对象只需要专注做自己的事情,其他的事情交给代理对象
public class StaticProxy {
public static void main(String[] args){
//传统写法
//You you = new You();
//you.happyMarry();
//创建代理对象 需要一个真实的对象参数
// WeddingCompany weddingCompany=new WeddingCompany(new You());
//代理对象去调用结婚方法 还可以进行其他的操作
// weddingCompany.happyMarry();
//开启多线程
new Thread(()-> System.out.println( "我爱你" )).start();
//简化代码
new WeddingCompany(new You()).happyMarry();
}
}
//结婚接口
interface Marry{
//人生四大喜事
//久旱逢甘露
//他乡遇故知
//洞房花烛夜
//金榜题名时
void happyMarry();
}
//我实现结婚接口 我是真实的角色 我去结婚
class You implements Marry {
@Override
public void happyMarry() {
System.out.println( "我要结婚了,好开心!" );
}
}
//婚庆公司也实现结婚接口 它是一个代理角色 帮助我结婚
class WeddingCompany implements Marry {
//代理谁-->真实目标角色
private Marry target;
//构造方法 把我们的真实角色进行传参
public WeddingCompany(Marry target) {
this.target = target;
}
@Override
public void happyMarry() {
//结婚之前的方法
before();
//这就是调用真实对象了
this.target.happyMarry();
//结婚之后的方法
after();
}
private void after() {
System.out.println( "结婚之后" );
}
private void before() {
System.out.println( "结婚之前" );
}
}