静态代理模式
- 真实对象和代理对象都要实现同一接口
- 代理对象要代理真实角色
- 代理对象可以做很多真实对象做不了的事情
- 真实对象专注做自己的事情
- 它是线程底部的实现原理,你只用
start()
,run()
交给JVM
Lamda表达式
- 目的是为了避免内部类定义过多
- 其实质是属于函数式编程的概念
(parms)->expression[表达式]
(parms)->statement[语句]
(parms)->{statements}
- 例
new Thread(()-> System.out.println("代澳旗,加油!")).start();
lamda
表达式的关键:函数式接口
函数式接口:只包含一个抽象方法,只有一个!!!
对于函数式接口,我们可以通过lamda
表达式来创建该接口的对象
线程五大状态
- 五大状态:创建,就绪,阻塞,运行,死亡
线程常见方法
- 线程停止
- 建议线程正常停止—>利用次数,不建议无限循环
- 建议使用标志位—>设置一个标志位
- 不要使用stop或者destory等过时或者JDK不建议使用的方法
- 线程休眠(sleep)
sleep(时间)指定当前线程阻塞的毫秒数
- 存在异常
InterruptedException
sleep
时间到后进入就绪状态- 可以模拟网络延时,倒计时
- 每个对象都有一把锁,sleep不会释放锁。
- 线程礼让(yield)
- 让当前正在执行的线程暂停,但不阻塞
- 让线程从运行状态转为就绪状态
- 让cpu重新调度,礼让不一定成功,看CPU心情
- 我本来都要准备运行了,出于礼貌。我重新出来,咱两重新竞争。所以有可能还是我抢赢了。
- 线程强制执行(join)
- 霸道,强制执行,少使用
- 线程优先级:
- java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行。
- 线程优先级用数字表示,范围从1~10
- 获取优先级:
getPriority().setPriority(int XXX)
- 守护线程:
- 线程分为用户线程(如
main线程
)和守护线程(如gc线程
)。正常线程都是用户线程 - 虚拟机必须确保用户线程执行完毕
- 虚拟机不用等待用户线程执行完毕
- 例如: 后台记录操作日志,监控日志,垃圾回收等。。。
线程同步安全
由于同一进程的多个线程共享同一块儿存储空间,在带来方便的同时,也带来了访问冲突问题,为了保证数据在方法中被访问时的正确性,在访问时加入锁机制
。Synchronized
,当一个线程获得对象的排它锁,独占资源,其他线程必须等待,使用后释放锁即可。
- 一个线程持有锁会导致其他所需要此锁的线程挂起。
- 在多线程竞争下,加锁,释放锁会导致比较多的上下文切换,和调度时延,引起性能问题。
- 如果一个优先级高的线程等待一个优先级低的线程释放锁,会导致优先级倒置,引起性能问题。
同步方法
- 由于我们可以通过private关键字来保证数据对象只能被方法访问,所以我们需要针对方法提供一套机制,这套机制就是
synchronized
关键字,它包括两种方法:synchronized方法和synchronized块 synchronized
方法控制对象的访问,每个对象对应一把锁,每个synchronized
方法都必须获得调用该方法对象的锁才能执行,否则线程会阻塞,方法一旦执行,就独占该锁,直到该方法返回才释放锁,后面被阻塞的进程才能获得这把锁,继续执行。缺点就是:若将一个大的方法申明为synchronized
将会影响效率,锁的太多,就会浪费资源。
同步块
- 同步块:
synchronized(Obj){}
,锁住的是对象,是需要修改的那个对象。 Obj
称之为同步监视器
Obj
可以是任意对象,但是推荐使用共享资源作为同步监视器。- 同步方法中无需指定同步监视器,因为同步方法的同步监视器就是
this
.就是这个对象本身,或者是class对象。
- 同步监视器的执行过程
- 第一个线程访问,锁定同步监视器,执行其中代码。
- 第二个线程访问,发现同步监视器被锁定,无法访问。
- 第一个线程访问完毕,解锁同步监视器。
- 第二个线程访问,发现同步监视器没有锁了,然后锁定并访问。
CopyOnWriteArrayList
- JUC并发包中的类。