• 多线程的创建、匿名内部类方式创建线程、定义、调度步骤


    多线程

    并发、并行

    • 并行 :
      具有在同一时刻干两件或两件以上事情的能力,几件件事同一时刻进行。(同时执行)
      情景 : 正在吃饭,有人打电话过来

                 一边吃饭,一边打电话
      

      当前事未完成事,可以同时干这件事和另一件事

    • 并发
      具有在某个时间段做两件或两件以上事情的能力,几件事情在同一个时间段进行。(交错执行)
      情景: 正在吃饭,有人打电话过来
      停下吃饭的动作,接听电话,接听完电话,继续吃饭。
      当前事未完成时,可以暂时停止这件事,去干另一件事

    • 非并行,非并发

          情景:    正在吃饭,有人打电话过来
      
                        继续吃饭,吃完饭再接听电话
      
           必须完成当前这件事才能去干另一件事
      

    进程、线程

    • 进程
      被加载入内存(RAM),正在运行的程序,且具有独立的功能
    • 线程
      进程的一个执行单元,负责进程中程序的执行,一个进程有多个线程
      线程相当于通向cup的一条道路
    • 程序、进程、线程 三者的关系
      程序 > 进程 > 线程
      一个程序至少有一个进程,一个进程至少有一个线程,含有多个线程的程序称为多线程程序。

    其他

    创建多线程

    两种方法:

    • 继承Thread类

        1.继承Thread类
      
         2.复写run()方法
      
         3.创建线程对象,调用start()方法,开启线程
      

      /**
      *创建一个多线程实现Thread类
      */
      public class SubThread01 extends Thread {
      @Override
      public void run() {
      for (int j = 0; j < 20; j++) {
      System.out.println("subThread====" + j);
      }
      }
      }

      public class SubThreadDemo01 {
      public static void main(String[] args) {
      //创建线程
      SubThread01 subth = new SubThread01();
      //开启线程
      subth.start();
      for (int i = 0; i < 20; i++) {
      System.out.println("main====" + i);
      }
      }
      }

    • 实现Runable接口

      1. 实现 Runable接口

      2. 复写run方法

      3. 创建线程对象

      4. 创建Thread类,放入线程对象
        Thread th = new Thread(线程对象)

      5. th.start()
        /**
        *使用Runable创建一个线程类
        */
        public class RunThread01 implements Runnable {
        @Override
        public void run() {
        for (int i = 0; i <20; i++) {
        System.out.println("runthread===" + i);
        }
        }
        }

        public class RunThreadDemo01 {
            public static void main(String[] args) {
                //创建线程对象
                RunThread01 rth = new RunThread01();
                //开启线程
                Thread th = new Thread(rth);
                th.start();
                for (int i = 0; i <20; i++) {
                    System.out.println("run_main" + i);
                }
            }
        
        
        }
        

    继承Thread类和Runable类的区别:

    1. 使用Runable,避免了单继承的局限性,类继承了Thread类就不能继承其他类。
    2. 增强了程序的扩建性,降低了程序的耦合性,实现了Runable将设置线程任务和开启新线程进行分离
      继承Runable接口,重写run()方法 ------》设置线程任务
      使用Thread将线程任务放进去调用start()方法 ------》设置线程任务
      使用对象注入的时候可以在配置文件中更改线程任务,不必跑到源码中修改

    Jvm开启多线程的原理

    • Jvm开启线程

    首先Jvm执行程序,执行到main方法时,通知OS系统开辟一条mian方法到CPU的路径,此时这条路径就称之为线程,当执行到另一个线程的start()方法时,Jvm又通知OS系统开辟一条到当前开启的线程的run()的路径,即线程。

    简介版:

    Jvm通知OS系统开辟一条main() -----> Cpu的线程(路径),主程序继续执行,开启另一个线程 ------->Jvm通知OS开辟一条通往开启线程run()方法的路径(线程)

    • 开启多线程时的堆栈分配

    每一个线程都分配有自己的栈,公用一个堆

    当一个线程停止,不影响另一个线程执行

    • 如何实现线程切换

    线程的切换实际上CPU在不同线程的栈上进行切换,CPU的执行代码依赖于各种寄存器,当线程被挂起时,就将寄存器的数值放在该线程的堆中,当CPU重新执行此线程时,将从栈中取出寄存器的数值,接着运行。

    CPU使用相同线程函数代码在不同的栈中切换

    Thread类的常用方法

    • String getName() : 获取线程的名字

        该方法只能有一个线程实例才能使用,不能直接Thread.getName();
      
        使用情况:
      
        1.在线程的run()方法中直接调用
      
        2.通过Thread.currentThread().getName()使用
      
         因为main线程没有实现Runable和继承Thread类,因此不能直接在main方法中调用getName(),要先获取      Thread对象      
      
    • Thread currentThread() :获取当前执行线程

    • setName() :设置线程名字

    • sleep(Long millis) :设置线程睡眠时间
      该类会抛出InterrupException:中断异常
      public class SubThreadDemo02 {
      public static void main(String[] args) throws InterruptedException {
      for (int i = 0; i < 60; i++) {
      Thread.sleep(1000);
      System.out.println(i);
      }
      }
      }

    使用匿名内部类创建线程

    • 什么叫匿名内部类
      即隐式的继承一个类或实现一个接口,匿名内部类是一个继承了该类或者实现了该接口的子类匿名对象。

    • 匿名内部类的分类
      继承一个类
      实现类的接口
      匿名内部类的最终产物是一个子类或实现类

      /**
       * 使用你匿名内部类来创建线程
       *匿名内部类特点:子类继承父类、重写方法、建立对象一步完成
       */
      public class RunThreadDemo03 {
          public static void main(String[] args) {
              /**
               * 创建一个继承Thread的内部类
               * 相当于一个多态,子类对象赋给父类对象使用   父类对象 = 子类对象
               */
              //1.继承父类Thread的匿名内部类
              new Thread() {
                  //2.重写方法
                  public void run() {
                      for (int i = 0; i < 20; i++) {
                          System.out.println(getName() + "=====" + i);
                      }
                  }
                  //3.创建对象,使用方法
              }.start();
      
              for (int j = 0; j < 20; j++) {
                  System.out.println("main=====" + j);
              }
      
              /**
               * 创建一个实现Rununable接口的内部类
               * 使用Runnable来接收这个内部类,再放入到Thread中
               *//*
      
              Runnable r = new Runnable() {
                  public void run() {
                      for (int k = 0; k < 20; k++) {
                          System.out.println(Thread.currentThread().getName() + "=====" + k);
                      }
                  }
              };
              Thread th = new Thread(r);
              th.start();*/
              /**
               * 直接将匿名内部类作为参数传入
               */
              new Thread(new Runnable() {
                  @Override
                  public void run() {
                      for (int k = 0; k < 20; k++) {
                          System.out.println(Thread.currentThread().getName() + "=====" + k);
                      }
                  }
              }).start();
          }
      }
      

    线程调度

    线程的调度由jvm虚拟机实现

    • 定义
      按特定机制给多个线程分配cpu的使用
      计算机只有一个cpu,一个cpu在任意时刻只能执行一条机器指令,线程只有获取cpu的执行权才能执行指令
      并发运行的意思是线程轮流的获得cpu的使用权,在运行池中,有多个就绪状态的线程等着cpu

    • 线程调度的分类

      1. 分时调度
        所有线程轮流使用cpu且使用cpu的时间片相同
      2. 抢占式调度
        让运行池中优先级别高的线程先使用cpu,若运行池的线程级别相同则随机选择一个线程获得CPU的执行权
        处于运行状态的线程会一直运行,直至它不得不放弃CPU
    • 设置线程的优先级
      setPriority() :设置线程优先级
      getPriority() :获取线程优先级

    其他

    金麟岂能忍一世平凡 飞上了青天 天下还依然
  • 相关阅读:
    2020 CCPC Wannafly Winter Camp Day2 K题 破忒头的匿名信(AC自动机+dp)
    CF1446C Xor Tree(01Trie)
    day04---系统重要文件
    day03--vi和vim快捷方式及操作系统目录介绍
    day02---虚拟机上网模式
    day01---操作系统安装环境准备
    django中一些快捷函数
    django中的一些装饰器用法
    auth模块的一些方法
    celery中异步延迟执行任务apply_anysc的用法
  • 原文地址:https://www.cnblogs.com/Auge/p/11323336.html
Copyright © 2020-2023  润新知