就绪队列:存储将要获得锁的线程,一个线程被唤起后,会进入就绪队列。
阻塞队列:存储被阻塞的线程,一个线程被wait后,就会进入阻塞队列,等待下一次被唤醒。
等待/通知机制
通过轮询可以实现线程间的通信,但是会耗费CPU的资源。
方法在同步方法或者同步块中调用
wait()方法是Object类的方法,将当前线程代码放入预执行队列,直到接到通知或被中断为止,被执行完成后,锁会自动释放。Wait(毫秒数)中可以设置等待时间,等到期以后自动唤起。
notify()方法是通知可能等待该对象的对象锁的其他线程,如果有多个线程等待,则由线程规划器随机挑选一个呈wait状态的线程,对其发出notify()。必须执行完notify()方法所在的同步块所在的方法后,才会释放锁。注意wait()和notify()方法的顺序,必须先要调用wait后再调用notify(),否则先执行了notify(),则wait()就没有办法唤起了,需要配合对象监视器synchronized(x)方法使用
notifyAll()方法可以使所有正在等待队列中等待同一共享资源的“全部”线程从等待状态退出,执行顺序也不一定。
wait()与notify()是生产消费者模式
注:wait方法释放锁,但是sleep方法不释放锁,notify执行完成后不释放锁,需要等待执行完notify()方法所在的synchronized代码块后才释放锁。
线程状态的切换
runnable状态:调用线程的start()方法,系统会为此线程分配CPU资源,如抢占资源成功则变为running状态。
blocked状态:系统阻塞状态,如遇到一个I/O等类似操作,则由running变为blocked状态。
管道进行线程间通信:字节流、字符流
通过管道流(pipeStream)实现不同线程间的数据通信。使用PipedInputStream和PipedOutputStream绑定连接,通过PipedReader和PipedWriter实现字符流的通信。
Join方法
使当前主线程进行等待。主线程想通过子线程执行完成之后再结束,join方法是等待线程对象销毁。方法join具有使线程排队运行的作用,使所属线程对象正常执行run方法中的任务,而使当前线程进行无限期的阻塞,等待附属线程x销毁后再继续执行线程后面的代码。
join(long):不管x线程是否执行完毕,时间到了并且重新获得锁,则当前线程会继续向后执行。
Join方法(long)和Sleep(long)的区别:
Join(long)执行后会释放锁,其他线程可以调用此线程中的同步方法。
Sleep(long)方法不释放锁
ThreadLocal的使用
变量值的共享可以使用public static变量的形式,所有线程都使用同一个public static变量。可以使用ThreadLocal使得每个线程绑定自己的值(虽然是静态变量,但是每个线程都是单独存放的私有数据)。实际的实现方式是将线程数据放入当前线程对象的Map中。
可以使用ThreadLocalExt实现ThreadLocal值的初始化。
InheritableThreadLocal的使用
使用InheritableThreadLocal类可以让子线程从父线程中取得值。