线程
线程:用户线程User 守护线程 Deamon 相当于用户线程的保姆,守护用户线程的
如果程序中没有用户线程的存在了,所有的守护线程自动结束,只要还有一个用户线程,就不会强制结束守护线程
默认所有的线程为用户线程
经典的守护线程案例,垃圾回收机制
设置守护线程: thread.setDaemon(true);
要求: 在线程开启start()方法之前使用
创建线程的方式:
1继承Thread类,重写run()方法
2实现Runnable接口,重写run()方法
优点:1)避免单继承的局限性 2)实现资源共享
静态的资源是属于类的,多个对象共享类的静态的内容,在静态区中
成员属于对象的.多个人对象,堆内存中就存在多个成员,互补影响
创建线程的第三种方式:(了解)
实现Callable接口,重写call()方法
优点:
可以有返回值
可以抛出异常
缺点:
使用复杂
线程状态+线程同步->线程通信
线程状态
线程状态: 5个
新生状态: 创建线程 new Thread()
就绪状态: 调用start(),就绪队列 中的线程等待cpu的调度
运行状态: cpu把时间片分配给哪一个线程,这个线程才会运行
阻塞状态: sleep()…
终止状态: 结束,死亡
注意:
1.一个线程一旦进入终止状态,没有办法恢复,重新创建也是新的线程
2.一旦进入阻塞状态,不能直接恢复到运行状态的,恢复到就绪状态
一个线程如何进入到死亡状态?
1.正常执行完毕 2.调用destroy(),stop() 3.通过添加标识判断 —推荐
一个线程如何进入到就绪状态?
1.调用start()方法
2.阻塞解除
3.yield 礼让
4.线程切换
一个线程如何进入到阻塞状态:
1.sleep()
2.join()
3.wait()
4.io操作
sleep(毫秒数) 线程睡眠|休息
抱着资源睡觉,告诉cpu在多少时间中不要把资源分配给我这个线程,因为处于阻塞状态,到时间了就恢复到就绪状态,这个时候cpu才能把资源分配给我
sleep()的使用不要在任何同步环境下,但是如果在同步环境下使用了,在休眠途中,是不会释放对象锁的
模式网络延迟
放大问题的可能性
yield
yield 礼让线程 高风亮节
把cpu的资源让出,让cpu重新分配,但是有可能又选择了原线程,可以选择了其他线程,给了其他线程能够获取资源的机会
synchronized控制线程安全问题: ****
前提: 当多个线程同时操作同一份资源的时候,才有可能出现线程不安全问题
办法:使用同步锁 synchronized ,控制多线程执行时,某一段重要的代码,排队执行,其他代码可以同时执行,有能提高效率,有能控制安全
使用方式:
同步方法 : 在方法上使用synchronized关键字
成员方法 : 对象,类,资源
静态方法 : 静态的内容是属于类的,锁这个静态方法相当于锁类
比较简单,但是范围太大,可能效率会低
同步块
synchronized(this|类|资源){
}
this: 锁对象
类名.calss: 只有一个,不变的对象内容,在类第一次加载金内存就存在了
资源: 成员属性
注意:
同步一定要同步不变的内容,变的内容锁不住,自定义类的对象地址
锁的范围太大了,效率太低,锁的范围太小了,锁不住
难点: 锁谁,this|资源|类|方法 锁的多大的范围
同步方法
锁的范围太大,效率低,但是简单,如果想要只锁该锁的代码提高效率,可以使用同步块
同步块 类.calss
锁类,相当于把这个类的所有对象,内容都锁住了,如果有些对象不需要锁,我们就只锁某一个对象
同步块 对象 this
锁对象,把这个对象所有的资源全部锁住了,如果指向锁住其中的某一个资源,建议可以锁资源
同步块 资源 (成员变量)
自定义引用数据类型的对象永远不变