推荐高洪岩的《Java多线程编程核心技术》,虽然很多代码都是纯粹为了炫耀技术,但看完之后再也不怕被多线程问倒了
随笔提一句,前面看了那多章同步代码块的内容,后面却发现lock完全可以取代。这本书在我看来可以砍掉一半,直接用Lock就好了。
问题1:用Java写代码来解决生产者——消费者问题。
使用lock实现,另外MQ消息队列的点对点模式也是同样的原理,以及duboo的发布订阅模式。
MY:关键是搞明白何时阻塞、唤醒相关线程;wait/nofityAll
1 2 hasv=false; 3 4 5 set() 6 { 7 lock.lock() 8 while(hasv==true) 9 { 10 condition.await(); 11 } 12 hasv=true; 13 condition.signal(); 14 } 15 finally lock.unlock(); 16 } 17 18 get() 19 { 20 和set类似相反 21 }
run.java:
10个AB线程一起启动,A使用set,B使用get。就会交替执行A和B。使hasv的值改变,可打印信息查看 i=0,i<10,i++ threadA[i].start() threadB[i].start()
问题2:原子操作
double、long是 64位的,32位系统会赋值两次(即两个原子操作),在多线程环境下,可能刚读高32位,低32位被其他写覆盖了。
因此使用volatile关键字,确保在并发环境中确保可见性、顺序性和一致性。一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。
精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。
volatile是程度较轻的
synchronized,
这个关键字非常不好控制,干脆不用为好。
使用场景:可以用在Long个double变量上,见上面原子操作
问题3:多线程实战
A 在顶置的偏光片切割利用到,主要矛盾是CPU运算耗时长,打开任务管理发现双核CPU总是占用50%,另一核心根本没使用。
于是改成多线程计算,计算次数是可预见的,直接粗暴的按照CPU核心数来创建线程数量。然后等待所有线程运算完毕,结果集合并。
B 手动实现消费者-生产者模式