1.现在有 T1、T2、T3 三个线程,你怎样保证 T2 在 T1 执行完后执行,T3 在 T2 执行完后执行?
答:使用join()
方法,让其强制运行,此线程强制运行期间,其他线程无法运行,必须等待此线程运行完成之后才能继续运行。
2.为什么我们要调用start()
方法时会执行run()
方法,为什么我们不能直接调用run()
方法?
答:直接调用run()
方法,和其他方法没啥区别,程序在主线程上按顺序进行,没有多线程的概念。start()
方法看源码则是调用了private native void start0();
这个方法,这是一个native
方法,调用了本地操作系统的底层函数实现的。从而让操作系统开启一个线程,此线程处于就绪状态,等待CPU
进行调度。而实现runnable
接口,run()
方法中就是线程主体,是在线程获得CPU
时间片时,被CPU
进行调用运行的。也就是说,此时run()
方法是线程处于运行状态下进行操作的。
3.在Java
中wait()
和sleep()
方法的不同?
答:sleep()
是Thread
类中定义的方法,而wait()
是Object
类中的方法。sleep()
方法为此线程睡眠一段时间,交出执行权,不会释放锁对象。进入到其他阻塞状态。可不在同步方法中执行。如果sleep()
时间到,就会重新进入到就绪状态。而wait()
和notify()
是联用的,只能在同步方法中使用。wait()
则是交出执行权,交出锁对象,进入到等待阻塞状态。然后等着被notify()
方法唤醒,进入到同步阻塞状态,拿到锁,然后进入就绪状态。
wait()
方法和notify()
方法:当一个线程执行到wait()
方法时(线程休眠且释放机锁),它就进入到一个和该对象相关的等待池中,同时失去了对象的机锁。当它被一个notify()
方法唤醒时,等待池中的线程就被放到了锁池中。该线程从锁池中获得机锁,然后回到wait()
前的中断现场。
参考:
http://blog.csdn.net/lv1817/article/details/44904761
http://blog.csdn.net/liuguangqiang/article/details/49180319
4.为什么wait
,notify
和notifyAll
这些方法不在Thread
类里面?
答:要分析这个程序,首先要理解notify()
和wait()
,因为这两个方法本来就不属于Thread
类,而是属于最底层的Object
基础类的,也就是说不光是Thread
,每个对象都有notify
和wait
的功能,为什么?因为他们是用来操纵锁的,而每个对象都有锁,锁是每个对象的基础,既然锁是基础的,那么操纵锁的方法当然也是最基础了。
另一种解释:一般来说,进行notify
和wait
操作的时候,需要找一个两个线程共享的对象(即相同锁对象)。同时,这两个线程如果要同步的话,必须共享一个同步锁。通常就用共享的同步锁来通信,而同步锁可以任意对象。所以notify
和wait
的机制必须在Object
,必须让任意对象都有这种功能。
5.Thread
类中的yield
方法有什么作用?
答:yield()
方法为线程的礼让。放弃此线程的执行权,放弃执行权之后,立马有资格被CPU
调用,因为放弃之后就能立马进入到CPU
可以执行的线程队列,所以有可能会发现放弃之后,却又立马执行的情况。