Egoistic_Flowers

Java多线程基础
Java多线程

f0f30996658f45427a3c7ee6d36c24e6

Java多线程

1 线程创建

1.1 继承Thread类

创建线程方式一:继承Thread类

  • 继承Thread类,重写run方法,调用start开始线程

1.2 实现Runnable接口

创建线程方式二:实现runnable接口

  • 实现runnable接口,重写run方法,执行start,开启线程

1.3 实现Callable接口

创建线程方式三:实现Callable接口

  • 实现Callable接口,重写call方法,创建执行服务,提交执行,获取结果,关闭服务

1.4 静态代理模式

  • 代理对象和真实对象需要实现同一个接口,代理对象代理真实角色
  • 代理对象可以做很多真实对象做不了的事 ,真实对象专注做自己的事情

main:

1.5 线程创建总结

2 线程状态

线程(1)

  • 新建状态:

    使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。

  • 就绪状态:

    当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。

  • 运行状态:

    如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。

  • 阻塞状态:

    如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:

    • 等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。
    • 同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。
    • 其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。
  • 死亡状态:

    一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。

2.1 线程停止

  • 线程停止:

    • 线程最好是正常停止
    • 需要停止线程设置一个标志位,通过设置标志位,改变标志位停止线程

2.2 线程休眠

  • sleep时间到达之后线程进入就绪状态
  • 每个对象都有一个锁,sleep不会释放锁

2.3 线程礼让

  • 线程礼让,让当前执行的线程暂停,不阻塞
  • 线程从运行状态变为就绪状态
  • 礼让不一定成功,根据CPU调度执行

2.4 线程强制执行

  • join,等待此线程执行完成才会执行其他线程,其他线程阻塞

2.5 观测线程状态

2.6 线程优先级

进入就绪状态的线程,线程调度器按照优先级决定哪个线程先执行

设置 获取优先级

2.7 守护线程

守护进程创建:

3 线程同步

3.1 线程同步机制

并发

同一个对象被多个线程同时操作

线程同步

多个线程访问一个对象,并且线程修改对象的值,这时候就需要线程同步,等待机制,多个同时访问对象的线程进入对象的等待池形成队列,一个线程使用完,下一个线程再使用

3.2 并发问题

例子1:抢票 没有线程同步,此时就会出现多个人抢一张票的情况,产生负数

例子2:多线程插入List,出现重复插入导致数据缺失

3.3 同步方法与同步块

同步方法:public synchronized void method()

  • synchronized 方法控制对对象的访问,每个对象对应一把锁,每个synchronized 方法都必须获得调用该方法的对象的锁才能执行,方法开始执行,就会独占该锁,直到执行结束才会释放锁,阻塞的线程才能获取这个锁

同步块:synchronized(obj){}

obj为同步监视器

  • Obj为获取锁的对象,执行同步块时会获取Obj的锁,进行线程同步
  • 同步方法默认同步监视器为this,或者为class

3.4 JUC安全类型集合

CopyOnWriteArrayList

类本身能实现线程同步,直接使用

3.5 死锁

死锁的四个必要条件

  • 1.互斥条件:一个资源只能被一个进程使用
  • 2.请求与保持:一个进程因请求资源而阻塞时,对已有的资源保持不是放
  • 3.不剥夺条件:进程已获得的资源,在未使用完之前不进行剥夺
  • 4.循环等待:若干进程之间形成头尾相连的循环等待资源的关系

3.6 Lock锁

ReentrantLock类实现了Lock,可以显式加锁与释放锁

4 线程通信

4.1 线程通信方法

wait()

  • 线程会一直等待,知道其他线程通知,与sleep不同,会释放锁
  • wait可以加参数毫秒,表示指定等待的时间

notify()

  • 唤醒一个处于的等待状态的线程

notifyAll()

  • 唤醒同一个对象所有调用wait()方法的线程

4.2 管程法

生产者/消费者模型

  • 生产者:负责产生数据的模块
  • 消费者:负责处理数据的模块
  • 缓冲区:生产者将生产好的数据放入缓冲区,消费者从缓冲区拿数据

4.3 信号灯法

通过一个标志位来判断生产是否完成,消费是否完成

5 线程池

提前创建好多个线程,放入线程池,直接获取使用,放回池内

  • 提高响应速度
  • 降低资源消耗
  • 便于管理线程

5.1使用线程池

posted on 2021-12-03 18:26  Egoistic_Flowers  阅读(30)  评论(0编辑  收藏  举报