wait与notify最好不要用。必定要用就要规划好所有的运行计划。由于它是与运行时相关的。 程序员
跟运行时相关的意思是,也许你在代码中有三个地方调用了这个对象的wait,也在三个地方调用了这个对象的notify,这个不是成对使用。成对使用是指运行时必须是一对一的。若是10次运行WAIT而没有获得10次NOTIFY,那么就会有线程被阻塞在阻塞队列中不得而出,程序就会死掉。 编程
而且,即便规划好了这样的NOTIFY,可是若是一不当心浪费掉了其中的几个NOTIFY,那么也会挺麻烦的。由于浪费掉的NOTIFY指它被调用的时机发生时,锁对象的等待队列中并无其它的线程。队列是空的。因此此次机会失败了。 安全
好比你能够随时调用一个对象的NOTIFY方法,这个操做跟MAP里面的REMOVE同样,它是没有反作用的。它要么REMOVE成功,要么什么都不干。若是它什么都不干,就说明你进行了错误的操做。而NOTIFY错误是致命的,除非你很幸运。也就是说由于你的规划原本就是错误的,因此错错得正,这个机会 是有的。 多线程
还要注意的就是WAIT队列与锁队列是不一样的。锁其实没有队列,它没有状态,只有行为。好比一个线程尝试获取一个锁,失败了就是失败了,可是不会被记录。由于同步操做是高效率的操做,底层是使用原语完成的。里面的原理很是复杂,特别在1.5之后,很是很是复杂。有一个逐渐严肃化的过程,从什么原子锁到轻量级锁,共享锁一大堆。可是你只要知道JAVA的同步效率很是高就能够了。你须要了解的不是SYNCHRONIZED快不快,而是你有没有正确同步你的对象,有没有正确理解或找到你的临界代码而且对这些代码加以正确的同步。以及有没有正确理解线程安全,同步嵌套,线程API的本质。 函数式编程
JAVA里面,线程API实际上是虚拟机的调度接口。是虚拟机暴露其执行机制的窗口。你在写线程相关的东西时,你其实已经在调度你的程序而并不仅是,好比说,做一个简单的同步或者什么东西。特别是在你开始使用sleep, wait, notify, join, yield, interrupt等这些方法时,系统极可能由于错误的调度陷入不可恢复的状态并进而使系统中止工做。这个一方面直接引发系统当机,另外一方面还能够引发内存泄漏。 函数
你对你的程序应该有一个完整的规划。你应该随时知道并控制你的程序运行。你应该知道全部的线程都在干什么,应该干什么,何时应该起动何时应该结束,系统稳定或待机状态的定义,系统状态的恢复,系统工做状态的描述,而且另一点:一旦系统陷入当机或内存泄漏,对这个的容错(线程容错)。 线程
其实函数式编程的兴起很大程度上就是由于多线程编程的困难。你要去控制机器,要去调度。因此又兴起一大堆的好比,进程代数。这是个黑洞,无底洞,OO原本就已经很难搞了,再加上个这个,我看程序员到最后都得要求飞天。否则再过几年可能什么都干不了啦。 设计
FP多是惟一的出路。 对象
其实多线程里面,就单独一个同步就根本就不具备任何可控制的特征。咱们用的库有同步,咱们上面的调用代码又有同步。其实常常的,好比你调用了一些库,但实际上这些库共享了不少的东西,但你不可能所有都知道或者说去研究这些东西,而它又不是线程安全的。这时候就麻烦了。再者,谁知道你要在什么地方用这些东西是吧? 接口
FP的问题是有限的内存。FP好像呈现出一种对内存的无止境的需求。若是能解决这个问题,FP的确比多线程好多了。
应该这么说,冯诺依曼从一开始就不是为多线程设计的。固然FP也不是,可是FP抽象程度足够高因此没有冯系统的问题。
咱们最终的目标仍然是问题域,而不是对机器与线程API的理解是吧。凭什么咱们要去理解机器的调用机制?