Java多线程-初识并发问题和静态代理

96 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 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( "结婚之前" );

    }

}

静态代理的特点

1 真实对象和代理对象都要实现同一个接口

2 代理对象要代理真实的角色

静态代理的好处

1 代理对象可以做很多真实对象做不了的事情

2 真实对象只需要专注做自己的事情,其他的事情交给代理对象