java线程相关概念及线程的各种状态

一、Lambda表达式

1.λ

  • λ希腊字母表中排序第十一位的字母,英语名称为Lambda
  • 避免匿名内部类定义过多
  • 其实质属于函数式编程的概念

2.为什么要使用lambda表达式:

  • 避免匿名内部类定义过多
  • 可以让代码看起来很简洁
  • 去掉了一堆没有意义的代码,只留下核心的逻辑

3.函数式接口

  • 理解Functional Interface(函数式接口)是学习java8 lambda表达式的关键所在

  • 函数式接口的定义

    • 任何接口,如果只包含唯一一个抽象方法,那么它就是一个函数式接口
    • 对于函数式接口,我们可以通过lambda表达式来创建接口的对象
  • lambda表达式的推导

    • //lambda表达式的推导
      //外部类->静态内部类->局部内部类->匿名内部类->lambda表达式简化
      public class LambdaTest {
          //2.静态内部类
          static class Like2 implements Ilikeable{
              @Override
              public void like() {
                  System.out.println("lambda静态内部类");
              }
          }
          public static void main(String[] args) {
              Ilikeable like = new Like();
              like.like();
              like=new Like2();
              like.like();
              //3.局部内部类
              class Like3 implements Ilikeable{
                  @Override
                  public void like() {
                      System.out.println("lambda局部内部类");
                  }
              }
              like=new Like3();
              like.like();
              //4.匿名内部类,没有类的名称,只能借助接口或者父类
              like=new Ilikeable() {
                  @Override
                  public void like() {
                      System.out.println("lambda匿名内部类");
                  }
              };
              like.like();
              //5.lambda表达式(JDK1.8),函数式接口,只有一个要需要重写的方法,所以不需要知道名称
              like=() ->{
                  System.out.println("lambda表达式");
              };
              like.like();
          }
      }
      //1.外部类
      class Like implements Ilikeable{
          @Override
          public void like() {
              System.out.println("lambda测试外部类");
          }
      }
      //外部接口
      interface Ilikeable{
          void like();
      }
      

    image-20220412161418651

  • lambda表达式的进一步简化

    • 多个参数,参数类型可省略(要不写全不写),括号必须保留

    • 多条语句,方法体括号必须保留

    • public class LambdaTest2 {
          public static void main(String[] args) {
              Ilovable love=(int i)-> {
                  System.out.println("I love you-->"+i);
              };
              love.love(520);
              //1.简化参数类型
              love=(i)-> {
                  System.out.println("I love you-->"+i);
              };
              love.love(521);
              //2.简化括号,如果有多个参数,则不能简化括号
              love=i-> {
                  System.out.println("I love you-->"+i);
              };
              love.love(522);
              //3.简化花括号,如果有多条语句,则必须用花括号
              love=i->System.out.println("I love you-->"+i);
              love.love(523);
          }
      }
      interface Ilovable{
          void love(int i);
      }
      

二、静态代理

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

  • 代理对象代理真实对象来进行事情的处理

  • 好处

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

    • 真实对象可以专注做自己的事情

//静态代理,与Thread的实现相似
public class StaticProxy {
    public static void main(String[] args) {
        You you = new You();
        WeddingCompany weddingCompany = new WeddingCompany(you);
        weddingCompany.marry();
        new Thread(new Runnable() {
            @Override
            public void run() {

            }
        }).start();
        new WeddingCompany(new IMarryable() {
            @Override
            public void marry() {
                System.out.println("test1");
            }
        }).marry();
        new WeddingCompany(()->System.out.println("test2")).marry();//lambda表达式
    }
}

//结婚接口
interface IMarryable{
    void marry();
}
//真实要结婚的对象
class You implements IMarryable{
    @Override
    public void marry() {
        System.out.println("我结婚了");
    }
}
//婚庆公司
class WeddingCompany implements IMarryable{
    private IMarryable target;

    public WeddingCompany(IMarryable target) {
        this.target = target;
    }
    @Override
    public void marry() {
        before();
        this.target.marry();//调用真实对象的marry方法
        after();
    }
    private void before() {
        System.out.println("结婚前要婚庆公司布置现场");
    }
    private void after() {
        System.out.println("结婚后婚庆公司要收尾款");
    }
}

三、线程的五大状态及方法

image-20220413114203030image-20220413114432701

  • 线程方法image-20220413114741091

  • 停止线程

    • 不推荐使用JDK提供的stop()、destroy()方法【已废弃】。

    • 推荐线程自己停止下来。

    • 建议使用一个标志位进行终止线程,当flag=false时,则终止线程运行。

    • //线程停止
      public class ThreadStopTest implements Runnable{
          private static boolean flag=true;
          public static void main(String[] args) {
              ThreadStopTest th=new ThreadStopTest();
      
              new Thread(th).start();
      
              for (int i = 0; i < 1000; i++) {
                  System.out.println("mainThread"+i);
                  if (i==400){
                      th.stop();
                  }
              }
          }
      
          @Override
          public void run() {
              int i=0;
              while(flag){
                  System.out.println("subThread"+i++);
              }
          }
          public void stop(){
              this.flag=false;
          }
      }
      
  • 线程休眠

    • sleep(时间)指定当前线程阻塞的毫秒数

    • sleep存在异常InterruptedException

    • sleep时间达到后线程进入就绪状态

    • sleep可以模拟网络延时,倒计时等

    • 第个对象都有一个锁,sleep不会释放锁

    • 模拟网络延时:

      • //线程休眠,模拟网络延时,可以放大问题的发生性
        public class ThreadSleep implements Runnable{
            private int ticketnum=10;
            @Override
            public void run() {
                while(true){
                    if (ticketnum<=0){
                        break;
                    }
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"买了第"+ticketnum--+"张票");//会出现数据的混乱,线程不安全,不同步
                }
            }
            public static void main(String[] args) {
                ThreadSleep testThread4 = new ThreadSleep();
                new Thread(testThread4,"刘备").start();
                new Thread(testThread4,"张飞").start();
                new Thread(testThread4,"关羽").start();
            }
        }
        
      • 模拟倒计时:

        public class ThreadSleep2 {
        
            public static void main(String[] args) throws InterruptedException {
                turnDown();
            }
            //模拟10s的倒计时
            public static void turnDown() throws InterruptedException {
                int num=10;
                while(true){
                    Thread.sleep(1000);
                    System.out.println(num);
                    num--;
                    if (num==0){
                        break;
                    }
                }
            }
        }
        
      • 1s打印1次时间

        import java.text.SimpleDateFormat;
        import java.util.Date;
        
        public class ThreadSleep2 {
        
            public static void main(String[] args) throws InterruptedException {
                //打印时间
                Date date=new Date(System.currentTimeMillis());//获取当前系统时间
                while(true){
                    //线程休眠1s
                    Thread.sleep(1000);
                    SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH mm ss");
                    System.out.println(simpleDateFormat.format(date));
                    date=new Date(System.currentTimeMillis());//更新当前时间
                }
            }
           
        }
        
  • 线程礼让(yield)

    • 礼让线程,让当前正在执行的线程暂停,但不阻塞,就是说让线程从运行状态进入到就绪状态。

    • 礼让不一定成功,由CPU调度。

    • public class ThreadYield implements Runnable{
          @Override
          public void run() {
              System.out.println(Thread.currentThread().getName()+"Thread start");
              Thread.yield();//下次执行依然由CPU调度
              System.out.println(Thread.currentThread().getName()+"Thread end");
      
          }
      
          public static void main(String[] args) {
              ThreadYield threadYield = new ThreadYield();
              new Thread(threadYield).start();
              new Thread(threadYield).start();
          }
      }
      
  • 线程合并(插队join)

    • Join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞

    • 可以想象成插队

    • 强制执行,会让线程阻塞,少用

    • package status;
      //线程合并,强制执行,可以理解为插队,少用
      public class ThreadJoin implements Runnable{
          @Override
          public void run() {
              for (int i = 0; i < 1000; i++) {
                  System.out.println("我是vip线程"+i);
              }
      
          }
      
          public static void main(String[] args) {
              ThreadJoin threadJoin = new ThreadJoin();
              Thread thread = new Thread(threadJoin);
              thread.start();
      
              //主线程执行
              for (int i = 0; i < 200; i++) {
                  if (i==100){
                      try {
                          thread.join();
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                  }
      
                  System.out.println("我是主线程"+i);
              }
          }
      }
      
  • 观测线程状态

    image-20220417131959333

    package status;
    //观测线程状态
    public class ThreadStatus {
        public static void main(String[] args) throws InterruptedException {
            Thread thread = new Thread(()->{
                for (int i = 0; i < 5; i++) {
                    try {
                        Thread.sleep(1000);//子线程休眠1s
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("子线程执行完毕");
            });
            //new状态,未调用start
            Thread.State state = thread.getState();
            System.out.println(state);
            //线程开始执行
            thread.start();
            state=thread.getState();
            System.out.println(state);
            //不结束则一直输出状态
            while(state!=Thread.State.TERMINATED){
                //主线程1S执行一次
                Thread.sleep(1000);
                state=thread.getState();
                System.out.println(state);
            }
    
        }
    }
    
  • 线程优先级:设置优先级后也是需要看CPU调度,并不一定按优先级执行,只是说优先级高的线程分配的“权重”大。

    • package status;
      
      //优先级0-10
      public class ThreadPriorityDemo01 {
          public static void main(String[] args) {
              //输出主线程的优先级,默认优先级为5
              System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
              SetPriorityTest setPriorityTest=new SetPriorityTest();
              Thread t1=new Thread(setPriorityTest);
              Thread t2=new Thread(setPriorityTest);
              Thread t3=new Thread(setPriorityTest);
              Thread t4=new Thread(setPriorityTest);
              Thread t5=new Thread(setPriorityTest);
              t1.setPriority(10);
              t1.start();
              t2.setPriority(8);
              t2.start();
              t3.setPriority(6);
              t3.start();
              t4.setPriority(4);
              t4.start();
              t5.setPriority(1);
              t5.start();
          }
      }
      
      class SetPriorityTest implements Runnable{
          @Override
          public void run() {
             System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
          }
      }
      
    • image-20220418150008619

  • 守护线程:

    • 所谓守护线程,是指在程序运行的时候在后台提供一种通用服务的线程,比如垃圾回收线程就是一个很称职的守护者,并且这种线程并不属于程序中不可或缺的部分。因此,当所有的非守护线程结束时,程序也就终止了,同时会杀死进程中的所有守护线程。反过来说,只要任何非守护线程还在运行,程序就不会终止。

    • 用户线程和守护线程两者几乎没有区别,唯一的不同之处就在于虚拟机的离开:如果用户线程已经全部退出运行了,只剩下守护线程存在了,虚拟机也就退出了。 因为没有了被守护者,守护线程也就没有工作可做了,也就没有继续运行程序的必要了。

    • 线程分为用户线程和守护线程,正常的线程都是用户线程

    • 虚拟机必须确保用户线程执行完毕

    • 虚拟机不用等待守护线程执行完毕

    • package status;
      public class GodAndYouDemo {
          public static void main(String[] args) {
              God god=new God();
              You you=new You();
              Thread godThread=new Thread(god);
              Thread youThread=new Thread(you);
              godThread.setDaemon(true);//默认为false
              godThread.start();
              youThread.start();
          }
      }
      //God,守护者(守护线程)
      class God implements Runnable{
          @Override
          public void run() {
              while(true)
              System.out.println("我是god,我一直在守护着you");
          }
      }
      //You,被守护者(用户线程)
      class You implements Runnable{
          @Override
          public void run() {
              for (int i = 0; i <100; i++) {
                  System.out.println("我是you,这是我的第"+i+"天");
              }
              System.out.println("===Good bye===");
          }
      }
      
    • 用户线程执行完成后,守护线程在运行一会自动退出

    • image-20220418152127822

posted @ 2022-05-01 09:57  是韩信啊  阅读(25)  评论(0编辑  收藏  举报