多线程与高并发(1)
创建线程的方式
- 继承Thread类
- 实现Runnable接口
- 使用Lambda表达式(第二种的变形)
启动线程的三种方式
- Thread
- Runnable
- Executors(线程池)
线程中的方法
Thread.yield():让出cpu,让线程回到就绪状态。
join():在线程执行过程中加入另外一个线程,并且等待这个线程执行完才继续执行。
Thread.sleep(millis):暂停当前线程的执行,暂停时间由方法参数指定,时间过后自动回到就绪状态。
getState():获取线程状态(New Runnable Teminated TimedWaiting Waiting Blocked)。
interrupt():抛出InterruptedException异常。
Synchronized关键字
- synchronized锁定的是对象不是代码。
- synchronized方法与synchronized(this)是等效的。
- synchronized静态方法与synchronized(T.class)是等效的。
- synchronized是可重入锁。
- synchronized同步区异常会释放锁,导致其他线程乱入,如果不想释放,需要catch。
- synchronized锁定的对象不能不包括String常量和Integer、Long、Double等等基础数据类型对象。
synchronized的底层实现
JDK早期synchronized是重量级的。后来改进:锁升级的概念(hotspot实现)
当线程获取锁,先在锁对象头部markword记录这个线程ID(偏向锁);
如果出现线程争用,升级为自旋锁;
默认自旋10次后还未获得锁,则再升级为重量级锁(去OS获取资源)
关于自旋锁
执行时间短(加锁代码),线程数少,用自旋。
执行时间长,线程数多,用系统锁。