线程基本状态图
图中是线程运行的基本状态:线程调用start()方法开始后,就进入到可运行状态,随着CPU的资源调度在运行和可运行之间切换;遇到阻塞则进入阻塞状态。二三的状态图中只不过线程被阻塞的情况分为很多种,后面的图是细化说明。
New --> Runnable
当一个线程执行了start方法后,不代表这个线程就会立即被执行,只代表这个线程处于可运行的状态,最终由OS的线程调度来决定哪个可运行状态下的线程被执行。
Running --> Runnable
- Thread.yield()
- 一个线程一次被选中执行是有时间限制的,这个时间段叫做CPU的时间片,当时间片用完但线程还没有结束时,这个线程又会变为可运行状态,等待OS的再次调度;
Running --> Blocked
- 在一个运行中的线程等待用户输入
- 调用Thread.sleep()
- 调用了其他线程的join()方法
Blocked --> Runnable
- 阻塞状态的线程用户输入完毕
- sleep时间到
- join的线程结束
同步的线程状态图
Lock pool --> Runnable
当资源被一个线程访问时,上锁,其他线程就进入了一个锁池(Lock pool);当锁被释放,其他线程获得了锁,就变为可运行状态。
加入线程间的相互作用
线程调用了wait()方法之后,释放掉锁,进入等待池(Wait pool) ;收到通知之后等待获取锁,获取锁之后才可以运行。
线程被阻塞可能是由于下面五方面的原因:(《Thinking in Java》)
1.调用sleep(毫秒数),使线程进入睡眠状态。在规定时间内,这个线程是不会运行的。
2.用suspend()暂停了线程的执行。除非收到resume()消息,否则不会返回“可运行”状态。
3.用wait()暂停了线程的执行。除非线程收到notify()或notifyAll()消息,否则不会变成“可运行”状态。
4.线程正在等候一些IO操作完成。
5.线程试图调用另一个对象的“同步”方法,但那个对象处于锁定状态,暂时无法使用。
线程同步各个方法的区别
- Thread.yield()当前运行的线程变成可运行状态。
- t2.join() 使得当前线程处于阻塞状态直到t2线程执行完毕。
- Thread.sleep()使得当前线程处于阻塞状态直到sleep的时间结束。
- wait、notify、notifyAll方法是Object类的方法,其调用环境必须有synchronized的同步块中调用,否则会抛java.lang.IllegalMonitorStateException异常。