10. 匿名内部类创建多线程——你们老师喜欢的
将Runnable
接口进行匿名处理
11. 发现问题,提出synchronized的概念和用途
现实情况中,抢鞋肯定是有延时操作的,如果我们用.sleep()
设置每次抢鞋之间的间隙,会产生了一个问题,就是线程不同步导致线程不安全,两个人同时抢了第7双鞋
解决这个问题要用到线程同步,及时更新数据,即创建一个synchronized
锁对象,同步数据
12. synchronized同步方法
如何理解锁呢?当用户一抢到第一双鞋时,锁住第一双鞋,其它用户就无法抢了
synchronized
可以创建成一个同步方法,将同步代码块抽离出来
13 Lock、ReentrantLock同步锁
synchronized与reentrantLock区别
synchronized
不需要用户去手动释放锁,代码执行完后系统会自动让线程释放对锁的占用
reentrantLock
则需要用户去手动释放锁,如果没有手动释放锁,就可能导致死锁现象
14. Unlock遗留问题,释放锁
释放reentrantLock
锁,try catch
要放在if
外面,最后finally
调用reentrantLock.unlock()
方法
15. 浅谈synchroized和Lock的区别
- JDK1.5中,
synchroized
是重量级操作,性能低效,Lock
性能高,更稳定
- JDK1.6中,
synchroized
加入很多优化,更加稳定了
锁的释放
synchronized
以获取锁的线程执行完同步代码,如果线程执行发生异常,jvm会让线程释放锁
Lock
在finally
中必须释放锁,不然容易造成线程死锁
死锁产生
synchronized
在发生异常时候会自动释放占有的锁,不会出现死锁
Lock
发生异常时候,不会主动释放,必须手动unlock
来释放锁,可能引起死锁的发生
用法
synchronized
在需要同步的对象中加入,可以加在方法上,也可以加在特定代码块中,括号中表示需要锁的对象
Lock
一般使用ReentrantLock
类做为锁,通过lock()
加锁和unlock()
解锁指出,在finally
中写unlock()
防止死锁
16. Thread API说明
参考:Thread (Java Platform SE 7 ) - Oracle
17. CPU线程调度、Priority线程优先级、优先级常量、剩余小问题
CPU线程调度
- 每一个线程的优先使用权都是系统随机分配的,人人平等,谁先分配到谁先用
- 可以设置优先级赋予某一个线程拥有至高适用权,最高为10,最低为1,默认为5,Java可以抢占CPU
线程1-10中,main()
主线程的value = 5,创建 MaxPriorityThread
类和MinPriorityThread
来查看线程执行顺序
在.start()
前面加优先级.setPriority()
方法即可越权
但有时会发现优先级没有调换过来,是操作系统的原因,程序执行太快了没有反应过来,还没调度程序就结束了
18. join线程插队
.join()
方法可以抢占优先级,实现插队
19. sleep线程休眠
还是上一个例子,使用.sleep()
方法休眠后,thread_1
线程插队时,会等待1000毫秒再打印出结果
20. yield线程让步
.yield()
方法可以实现线程让步,让其它线程执行,thread_1
输出一次的时候给thread_2
让步了,有时程序运行的太快了,以至于还没打印出让步输出,thread_2
已经输出完毕了
21. 线程状态?嗯,还是来玩一盘游戏吧!
Java中线程的状态分为6种–以斗地主为例
1.新建(NEW)-新建一局游戏
2.可运行(RUNNABLE)-初始状态是可运行的
3.阻塞(BLOCKED)-谁出牌谁获得一个锁,导致阻塞,出好牌则疏通阻塞
4.等待(WAITING)-不出牌的等待通知
5.计时等待(TIMED_WAITING)-出牌时,其他人计时等待超时或通知
6.终止(TERMINATED)-游戏结束
22. 发现实际问题,抛出线程通信的含义
线程优先级
- Win10任务管理器中,线程有6个优先级设置
- 线程的调度目的就是通知另一个线程去执行,也有其它办法去通知
23. 线程的通信:wait和notify
线程通信,即等待唤醒机制
- 最简单的例子如
Producer
生产者与Customer
消费者和Condom
产品的关系
- 当产品
Condom
产品生产出来之后,消费者购买完,需要联系Producer
厂商继续生产
.notify()
方法用于唤醒一个在此对象监视器上等待的线程
- 一个线程在对象监视器上等待可以调用
.wait()
方法
24. notifyAll
.notifyAll()
方法用于唤醒在该对象上等待的所有线程
25. 提及Process进程。点到为止,章节结束语和建议。
多线程掌握基础,当学习到框架时,需要深入并发编程
参考:操作进程拓展Class ProcessBuilder