Thread 和Runnable
线程五种状态:
- 创建
- 运行
- 消亡
- 临时状态阻塞 具备运行资格但是没有执行权(cpu没有分配任务))
- 冻结状态(放弃执行权)
同步代码块
Object object = new Object();
public void run(){
while(true){
synchronized(object){
//同步代码块
}
}
}
实现方式和继承方式区别
避免单继承局限性。
同步的前提
必须要有两个或两个以上的线程
必须多个线程使用同一个锁
必须保证同步中只有一个线程执行
好处:线程安全
缺点:运行效率变慢
明确问题:
明确哪些代码是多线程代码
明确共享数据
明确多线程运行代码中哪些代码执行共享数据
同步函数用的锁是this
静态同步函数用的锁不是this,因为静态没有对象就没有this, 所以用的锁是 类 .class
死锁:
同步嵌套同步, 锁还不一样
锁的唤醒机制
wait:
notify();
notifyAll();
都使用在同步中,因为要对持有监视器(锁)的线程操作
所以要使用在同步中,因为只有同步才有锁
为什么这些操作线程的方法要定义在object类中?
因为这些方法在操作同步中线程时,都需要标识他们所操作线程持有的锁,
只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒。
不可以对不同锁中的线程进行唤醒。
也就是说,等待和唤醒必须是同一个锁
而锁是任意对象, 所以可以被任意对象调用的方法定义在object类中
notifyAll 唤醒所有线程,会不会造成并发问题?
如果线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁。当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。也就是说,调用了notify后只要一个线程会由等待池进入锁池,而notifyAll会将该对象等待池内的所有线程移动到锁池中,等待锁竞争
jdk1.5 提供了多线程升级解决方案(lock 替换synchronized)
将同步中synchronized替换成显示lock操作。将obejct中的wait,notify, notifyAll替换成了condition对象,该对象可以lock锁,进行获取
利用不同的condition对象, 对对方进程进行唤醒
最好的例子(生产者和消费者)
在 1.5之前需要循环判断标志位并且notifyAll()
利用不同condition 指定唤醒对方的线程
线程停止:
stop方法已经过时
如何停止线程
只有一中方法,run方法结束
开启多线程运行,运行代码通常是循环结构
只要控制住循环,就可以让run方法结束,也就是线程结束
特殊情况:
当线程处于了冻结状态。
就不会读取到标记,那么线程就不会结束
解决办法:
当没有指定的方式让冻结的线程回复到运行状态时,这时需要对冻结进行清除。
强制让线程回复到运行状态中来。这样就可以操作标记让线程结束
Thread类提供该方法 interrupt(), 会抛出interruptException异常, 处理异常,然后继续运行