目录

多线程


多线程

1 概念

1.1 程序

  • 为了完成某个任务或功能,选择某个编程语言而编写的一组代码指令的集合

1.2 进程

  • 程序的一次运行,是操作系统管理和调度的最小单位,每一个进程之间内存是相互独立的,如果进程之间要通信比较麻烦,可以通过文件,或网络通信方式等

1.3 线程

  • 是进程中的其中一条执行路径,是 CPU 调度任务的最小单位

    • 线程是共享同一个进程的内存

2 如何开启主线程以外的线程

2.1 方式一:继承 java.lang.Thread 类

  • 步骤

    - ①继承Thread类
    

    ② 重写 public void run(){} 编写线程体,即该线程需要完成的任务代码 ③ 创建线程对象 ④ 启动线程:线程对象.start();

2.2 方式二:实现 java.lang.Runnable 接口

  • 步骤

    - ①实现java.lang.Runnable接口
    

    ② 实现 public void run(){} 编写线程体,即该线程需要完成的任务代码 ③ 创建线程对象 ④ 启动线程:借助 Thread 类的对象 new Thread(自定义线程对象).start();

2.3 经典面试题

  • 两种方式的区别

    - 区别:
    

    (1)继承 Thread 类会有单继承的限制 实现 Runnable 接口不会有单继承的限制 (2)继承 Thread 类的方式,共享数据方面比较麻烦,使用 static 方式 实现 Runnable 接口,共享数据时,只需要共用同一个的 Runnable 接口的实现类的对象即可 (3)继承 Thread 类的方式,同步的锁的选择要么选择一个 static 对象作为锁,要么选择“类名.class 即当前类 Class 对象” 实现 Runnable 接口,同步锁可以直接选择 this 对象

3 线程安全问题

3.1 前提条件

  • (1)有多个线程 (2)共享数据 (3)多条语句操作共享数据

3.2 解决方法

  • 同步 synchronized

    - 形式
    
    	- 同步代码块
    
    		- synchronized(锁对象){
    同步代码,即需要加锁的代码
    

    }

    	- 同步方法
    
    		- synchronized [修饰符] 返回值类型 方法名(形参列表)抛出的异常列表
    
    - 同步锁
    
    	- (1)任意类型的对象
    

    (2)保证使用共享数据的多个线程,共用同一个锁对象

    - 锁的范围
    
    	- 同步代码块:范围
    

    (1)不能太大:机会不均匀 (2)不能太小:安全问题没解决 (3)最好锁一次任务代码

    - 同步方法的锁:
    
    	- 静态方法的锁:当前类的Class对象,即当前类名.class
    

    非静态方法的锁:当前对象,this

4 线程通信

4.1 问题:生产者消费者问题

  • 问题

    • 现象描述

      • 有多个线程共享一个缓冲区(例如:数据仓库,文件等),有的线程往里放数据,有的线程往外取数据

        • 问题有两个

          • 问题:线程安全问题

            • 因为有共享数据
            • 如何解决:同步
          • 问题:缓冲区大小有限的

            • 如何解决:线程通信

4.2 线程通信的方法

  • (1)wait() (2)notify()和 notifyAll()

    - 在java.lang.Object
    
    	- 为什么?
    
    		- 线程通信依赖于锁对象,即wait()和notify()是由锁对象调用
    		- 锁对象可能是任意类型的对象,那么这些方法只能在Object类中声明
    
  • 面试题:wait()和 sleep()的异同?

      • 这两个方法都会导致当前线程从运行状态到阻塞状态
    • 不同

      • 从阻塞回到就绪状态

        • sleep()睡眠时间到了
        • wait()也可以设置时间,但更多时候是通过 notify()
      • 声明的类不同

        • wait 是 Object 中,非静态方法
        • sleep 是 Thread 类中,静态方法
      • 锁释放问题

        • sleep:不会释放锁的

          • 例如:在卫生间睡着了,锁还在手上
        • wait():会释放锁的

          • 例如:抢到锁了,但是因为一些条件不满足,就释放锁,由其他线程执行

5 java.lang.Thread

5.1 方法

  • 1、获取线程名称的方法

    • getName()
  • 2、获取当前线程对象

    • Thread.currentThread()
  • 3、线程休眠

    • Thread.sleep(毫秒)
    • Thread.sleep(毫秒,纳秒)
  • 4、线程的优先级

    • getPriority()

    • setPriority()

      • 优先级的范围是 1-10

        • MAX_PRIORITY:10
        • MIN_PRIORITY:1
        • NORMAL_PRIORITY:5
    • 注意:业务逻辑不能依赖于优先级

  • 5、加塞

    • join()

      • 这句代码写在那个线程体中,哪个线程被加塞,被调用这个 join()的线程加塞
  • 6、run():所有线程都要写

  • 7、start():启动线程

5.2 生命周期