关于Java多线程

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/shuangmulin45/article/details/89344126

关于Java多线程

  1. 线程状态
    • 新建状态(NEW)。当线程被new出来的时候的状态为新建状态
    • 就绪状态(RUNNABLE)。当线程准备就绪,即调用start方法之后为就绪状态
    • 运行状态(RUNNING)。当线程拿到cpu执行权已经开始执行的状态为运行状态,注意,运行状态只能从就绪状态进入
    • 阻塞状态。
      • 调用sleep方法或者有io方法阻塞,这种阻塞只是暂停线程,并不会放弃cpu执行权。具体在api上有注释说明:The thread does not lose ownership of any monitors.
      • 调用wait方法,这个方法会释放cpu的执行权,知道其它线程调用notify或notifyAll方法将它唤醒,注意唤醒之后并不是直接进入运行状态,而是进入就绪状态,和其它线程一起参与锁的竞争。api上的注释原话解释的很清楚:The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the {@code notify} method or the {@code notifyAll} method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.
      • 竞争锁失败,线程会在锁池里阻塞
    • 死亡状态。线程执行完毕或者因为异常退出。
详细理解线程阻塞状态

阻塞状态应该有更细分的状态,这样才更好理解。
细分为:

  • 等待队列
    • 线程调用wait方法就会进入这个状态,即不再参与锁的竞争
  • 锁池状态
    • 所有有资格竞争锁的线程都在这个队列,线程被notify唤醒之后就是这个状态,这个状态的线程一旦获取到锁就会进入就绪状态,然后被cpu分配时间片进入运行状态
  • “阻塞”状态
    • sleep和io阻塞就是这个状态,不会释放cpu执行权,随时会进入运行状态
      在这里插入图片描述
notify和notifyAll

notify是随机唤醒一个被wait方法放在在等待队列里的线程,从而进入锁池状态参与锁的竞争
notifyAll是唤醒所有被wait方法放在在等待队列里的线程

join

假设有线程a和线程b,如果线程a调用线程b.join(),意味着a线程会阻塞到b线程执行完才继续执行。

最后有关wait的使用

在Effective Java这本书上,有一个点,说wait方法的调用必须要放在while循环里面做,永远不要放在循环外面用if判断来做。Always use the wait loop idiom to invoke the wait method; never invoke it outside of a loop.

synchronized (lock) {
	while (<执行条件还没有满足>) {
		lock.wait();
	}
}

这其实很好理解,就只是为了保证一旦线程在条件还没满足的时候就被唤醒程序也不会出错。

猜你喜欢

转载自blog.csdn.net/shuangmulin45/article/details/89344126