Java多线程Day01-多线程之多线程基本概念

基本概念

  • Java多线程内容:
    • Object类中的wait(),notify() 等接口
    • Thread类中的接口
    • synchronized关键字
  • JUC是指java.util.concurrent

线程状态图

  • Java中线程的状态分为6种: 新建状态New, 运行状态Runnable( 包括就绪状态ready和运行状态running), 阻塞状态Blocked, 等待状态WAITING, 超时等待状态 (TIMED_WAITING), 终止状态TERMINATED(消亡状态Dead)
    在这里插入图片描述

  • 新建状态NEW: 新创建了一个线程对象,但还没有调用start() 方法

    • 线程对象被创建后,就进入了新建状态
    • 实现Runnable接口和继承Thread可以得到一个线程类 ,new一个实例出来,线程就进入了初始状态
    • 比如 : Thread thread = new Thread();
  • 运行状态RUNNABLE: Java线程中将就绪状态Ready和运行状态Running统称为运行状态Runnable

    • 就绪状态Ready: 线程对象创建后,其余线程调用该对象的start() 方法.该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态
      • 调用线程的start() 方法,此线程进入就绪状态
      • 当前线程sleep() 方法结束,其余线程join() 结束,等待用户输入完毕,某个线程拿到对象锁,这些线程也将进入就绪状态
      • 当前线程时间片用完了,调用当前线程的yield() 方法,当前线程进入就绪状态
      • 锁池里的线程拿到对象锁后,进入就绪状态
      • 就绪状态只是表示线程可以运行,如果调度程序调度到线程,线程就永远处于就绪状态
    • 运行状态Running: 就绪状态的线程在获得CPU时间片后变为运行状态
      • 线程调度程序从可运行池中选择一个就绪状态Ready的线程进行调度
      • 这是线程进入运行状态的唯一方式
  • 阻塞状态BLOCKED: 线程阻塞于锁

    • 线程阻塞在进入synchronized关键字修饰的方法或代码块获取锁时的状态
  • 等待状态WAITING: 进入该状态的线程需要等待其余线程做出一些特定动作,比如通知或中断

    • 处于这种状态的线程不会被分配CPU执行时间
    • 等待被显式地唤醒,否则会处于无限期等待的状态
  • 超时等待状态TIMED_WAITING: 该状态不同于WAITING, 可以在指定的时间后自行返回

    • 处于这种状态的线程不会被分配CPU执行时间
    • 不需要无限期等待被其余线程显式地唤醒,在达到一定时间后会自动唤醒
  • 终止状态TERMINATED: 线程已经执行完毕

    • 当线程的run() 方法完成时,或者主线程的main() 方法完成时,就认为线程终止
    • 线程对象也许是活的,但是已经不是一个单独执行的线程.线程一旦终止,就不能复生
    • 在一个终止的线程上调用start() 方法,会抛出java.lang.IllegalThreadStateException异常

等待队列

  • 调用objwait(),notify() 方法前,必须获得obj锁.即wait()notify() 方法必须写在synchronized(obj) 代码内
    在这里插入图片描述
  • 线程1获取对象的锁,正在使用对象A
  • 线程1调用对象Await() 方法
  • 线程1释放对象A的锁,进入等待队列
  • 同步队列的线程争抢对象锁
  • 线程5获取对象的锁,使用对象A
  • 线程5调用A对象的notifyAll() 方法唤醒所有等待线程
  • notifyAll() 方法所在的synchronized结束,线程5释放对象A的锁
  • 同步队列的线程争抢对象锁

Object类

  • wait()
  • notify()
  • notifyAll()

Thread类

  • 线程休眠函数 : sleep()
  • 线程中断函数 : interrupt()
  • 获取线程名称 : getName()

synchronized关键字

  • 分为synchronized代码块和synchronized方法
  • 作用: 使得线程获取对象的同步锁

同步队列

  • 当前线程调用对象A的同步方法时,发现对象A的锁被其余线程占用,此时当前线程进入同步队列. 即同步队列中的线程都是准备争抢对象锁的线程
  • 当一个线程1被另外一个线程2唤醒时,线程1进入同步队列,去争抢对象锁
  • 同步的环境下才会有同步队列.一个对象对应一个同步队列
  • 超时等待线程到了等待时间或者等待线程被notify() 方法或者notifyAll() 方法唤醒,会进入同步队列中去竞争锁:
    • 如果获得锁,则进入运行状态RUNNABLE
    • 如果没有获得锁,则进入阻塞状态BLOCKED等待获取锁

Thread中的方法

Thread.sleep(long millis)

  • 作用: 给其余线程执行的机会
  • 一定是当前线程调用此方法
  • 当前线程进入超时等待状态TIMED_WAITING, 不释放对象锁, millis后线程自动苏醒进入就绪状态

Thread.yield()

  • 作用:
    • 使得相同优先级的线程轮流执行,但是并不保证相同优先级的线程一定会轮流执行
    • 实际中无法保证yield() 达到让步目的,因为让步的线程还有可能会被线程调度程序再次选中
    • Thread.yield() 不会导致线程阻塞,该方法与sleep() 类似,只是不能由用户指定暂停多长时间
  • 一定是当前线程调用此方法
  • 当前线程放弃获取的CPU时间片,不释放资源,由运行状态Running转变为就绪状态Ready, 重新选择执行线程

thread.join

  • 包括 : thread.join()thread.join(long millis)
  • 当前线程调用其余线程的join方法,当前线程进入等待状态WAITING或者超时等待状态TIMED_WAITING. 当前线程不会释放已经持有的对象锁
  • 调用的其余线程执行完毕或者超时等待时间millis时间结束,当前线程进入RUNNABLE状态,也可能进入BLOCKED状态

obj.wait()

  • 当前线程调用对象的wait() 方法,当前线程释放对象锁,进入等待队列
  • 进入等待队列的线程依靠notify() 或者notifyAll() 唤醒
  • 如果是调用对象的超时等待方法wait(long timeout), 则超时等待时间timeout时间结束自动唤醒

obj.notify()

  • 唤醒此对象监视器上等待的单个线程,选择是任意性的

obj.notifyAll()

  • 唤醒在此对象监视器上等待的所有线程

LockSupport

  • 包括LockSupport.park(), LockSupport.parkNanos(long nanos), LockSupport.parkUntil(long deadlines)
  • 当前线程进入等待状态WAITING或者超时等待状态TIMED_WAITING
  • 不需要获得锁就可以让线程进入等待状态WAITING或者超时等待状态TIMED_WAITING
  • 需要通过LockSupport.unpark(Thread thread) 方法唤醒线程

猜你喜欢

转载自blog.csdn.net/JewaveOxford/article/details/107977191