Java基础 - 多线程

六眼飞鱼酱① 提交于 2020-01-15 01:01:18

多线程

  1. 概念详解:
    • 并行 和 并发两者的区别:
      • 并发:指两个或多个事件在同一个时间段内发生(同一时间段发生)
      • 并行:指两个或多个事件在同一时刻发生(同时发生)
    • 线程 和 进程两者的区别:
      • 线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程 中是可以有多个线程的,这个应用程序也可以称之为多线程程序
      • 进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多 个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创 建、运行到消亡的过程。
      • 总结:就是一个程序至少是包含一个进程 一个进程至少是包含一个线程
    • 线程调度的方式: 两种方式
      • 分时调度 所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间
      • 抢占式调度 优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度
  2. 创建线程类:
    • 创建线程类的方式 和 步骤:
      • 定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把 run()方法称为线程执行体。
      • 创建Thread子类的实例,即创建了线程对象
      • 调用线程对象的start()方法来启动该线程
      public class Test {
          public static void main(String[] args) {
              MyThread mt = new MyThread("新的线程!");
              //开启新线程 
              mt.start();
              //在主方法中执行for循环 
              for (int i = 0; i < 10; i++) {
                  System.out.println("main线程!" + i);
              }
          }
      }
      class MyThread extends Thread {
          //定义指定线程名称的构造方法
          public MyThread(String name) {
              //调用父类的String参数的构造方法,指定线程的名称
              super(name);
          }
      
          /*** 重写run方法,完成该线程执行的逻辑 */
          @Override
          public void run() {
              for (int i = 0; i < 10; i++) {
                  System.out.println(getName() + ":正在执行!" + i);
              }
          }
      }
      
      
  3. 多线程的执行步骤:
    • 程序启动运行main时候,java虚拟机启动一个进程,主线程main在main()调用时候被创建
    • 随着调用mt的对象的 start方法,另外一个新的线程也启动了,这样,整个应用就在多线程下运行
    • 当执行线程的任务结束了,线程自动在栈内存中释放了 当所有的执行线程都结束了 那么进程就结束
  4. Thread类详解:
    • 构造方法:
      • public Thread() :分配一个新的线程对象
      • public Thread(String name) :分配一个指定名字的新的线程对象
      • public Thread(Runnable target) :分配一个带有指定目标新的线程对象(Runnable接口还没有讲到现在这里提一下)
      • public Thread(Runnable target,String name) :分配一个带有指定目标新的线程对象并指定名字
    • 常用的方法:
      • public String getName() :获取当前线程名称
      • public void start() :导致此线程开始执行; Java虚拟机调用此线程的run方法
      • public void run() :此线程要执行的任务在此处定义代码
      • public static void sleep(long millis) :使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)
      • public static Thread currentThread() :返回对当前正在执行的线程对象的引用
  5. 创建线程的三种方法 和 优略势:
    • 创建线程的方式:
      • 继承Thread类的方式 也是最简单的方式
      • 实现Runnable接口的方式
        • 使用的步骤:
          • 定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体
          • 创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正 的线程对象(代理模式 也就是上面的构造方法的第三种方式public Thread(Runnable target)
          • 调用线程对象的start()方法来启动线程
      • 实现Callable接口的方式 就是创建Callable接口的实现类 重写call方法
    • 不同中方式的优略势(也就是说 既然已经有了Thread类的方式 为什么还要有Runnbale接口的方式 或者说是Runnable方式的优点)
      • Runnable方式适合多个相同的程序代码的线程去共享同一个资源
      • Runnable方式可以避免java中的单继承的局限性
      • Runnable方式增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和线程独立
      • 线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类。
    • Java程序启动是最少启动的线程是:在Java程序启动中 最少启动两个线程 一个就是main线程 另一个就是垃圾回收线程 而JVM的启动实际上是一个进程的启动
    • 对示例中方式的改进:使用匿名内部类的形式来进行多线程的创建
  6. 线程安全问题:
    • 什么是线程安全:简单的说就是多线程环境下代码的运行 和 在单线程的运行结果是一致的 就是线程安全的
    • 线程安全问题出现的原因:线程安全问题都是由全局变量及静态变量引起的。若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步, 否则的话就可能影响线程安全。
    • 解决线程安全问题的方式:线程同步
      • 线程同步的三种方式:
        • 同步代码块 synchronized 关键字可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问

          synchronized(同步锁){
           需要同步操作的代码 
           }
          
          • 对象的同步锁只是一个概念,可以想象为在对象上标记了一个锁. 1. 锁对象 可以是任意类型。 2. 多个线程对象 要使用同一把锁
        • 同步方法 使用synchronized修饰的方法,就叫做同步方法,保证A线程执行该方法的时候,其他线程只能在方法外 等着

          public synchronized void method(){ 
          可能会产生线程安全问题的代码
          }
          
          • 对于非static方法,同步锁就是this。 对于static方法,我们使用当前方法所在类的字节码对象(类名.class)。
        • 锁机制(一种更加面向对象的机制)java.util.concurrent.locks.Lock Lock锁 加锁和释放锁的方法:

          • public void lock() :加同步锁
          • public void unlock() :释放同步锁
  7. 线程状态:线程的生命周期中有六种状态
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!