线程分为用户线程和守护线程。未设置setDaemon()的线程都为用户线程,虚拟机无须等待守护线程执行完毕。守护线程有垃圾回收,监控内存,日志审查…
线程创建
创建线程方式一:继承Thread类,重写run()方法;
创建线程方式二(推荐):实现Runnable接口,重写run()方法;
其中涉及静态代理! 好处:避免oop单继承局限性
创建线程方式三:实现Callable接口,重写call方法;
需要返回值类型以及抛出异常。
1.创建服务 2.提交执行 3.获取结果 4.关闭服务
线程启动使用start()方法
线程状态
新建 ——》就绪——》运行——》死亡
运行时有可能会阻塞,阻塞解除后会转入就绪状态,进而运行。
线程方法
线程停止:
最好利用次数让其自动停止,不建议死循环;
次之利用布尔标识符flag使其停止;
不建议用JDK自身方法使其停止。
线程礼让:
yield();方法不一定成功,看cpu心情。给线程设置优先级也要看cpu心情。
线程休眠:
sleep();大部分用于模拟延时,能扩大事故的发生可能性,此方法不会释放锁。
线程插队:
join();线程强制执行,使其它线程等待直至其执行完毕。也就是说会使主线程(或者说调用join()的线程)进入等待池并等待该线程执行完毕后才会被唤醒。并不影响同一时刻处在运行状态的其他线程。
线程等待:
wait();线程一直等待,它会释放锁。
线程唤醒:
notify();唤醒处于等待中的线程。
线程同步
线程同步形成条件:队列+锁
synchronized(隐式定义): 被其修饰的方法称为同步方法,此方法必须获得该方法对象的锁才能执行,否则线程会阻塞。synchronized关键字可定义在代码块和方法上,不可定义在run()上。在逻辑复杂,深度深的方法上不建议使用synchronized。
Lock(显式定义):——》ReentrantLock 可重入锁
private final ReentrantLock lock = new ReentrantLock();
try{
lock.lock();
......
}finally{
lock.unlock();
}
方法里需要涉及到修改的内容才需要锁,否则浪费资源,影响效率。
小知识
线程安全的集合: JUC包下的CopyOnWriteArrayList
死锁: 多个线程互相抱着对方需要的资源,然后形成僵持,程序卡死。
transient: 添加此关键字的属性在被序列化对象时不会被序列化
序列化: Java对象转化为字节文件(反序列化就是反过来)
voliate: 用于保持内存可见性,防止指令重排序。(可见性,原子性,有序性)
小句子
对人而言,沙粒不断坠落的过程就象征着光阴的流逝,但也不能单单认为这是自己的失去。
如果将我出生的那一刻定义为拥有全部时间的话,时光确实从我手中流逝了;
但如果将我死去的那一刻定义为我拥有了自己全部时间的话,那么,我一直都未曾失去过时间,而是一直在获取时间。
小故事
距离40世纪初的饥荒已过了20年,联邦命令我所属的部队进行新一轮大规模探索,以期找到更多适宜发展农业的殖民地。我奉命驾驶飞船飞向宇宙未知的深处,所过之处一片死寂,孤单是人本能的恐惧在离开了荒芜的LT-6号星之后,飞船探测到了微弱的引力场变动终于来了些有趣的东西,这让我提起了些兴趣,在一个陨石后面,捕获了一个简陋的小东西这是一个携带了一张金色圆形金属的原始飞行物难道附近星系有文明?这让我更加兴奋了。计算机粗略分析后指出,金属碟面的细小凹槽可能被录入了外形文明的音频或视频数据。我立刻命令计算机解析并播放音箱发出的却是一首古典的乐曲,正当我惊愕不已时,计算机解析完毕,提示音说道:欢迎回家,旅行者一号。
这是一个流行离开的世界,但是我们都不擅长告别。