2.1、同步方法
同步代码块:使用synchronized关键字包裹了一块代码,让这块代码同步执行。就是每次只能一个线程来执行。
同步方法:使用synchronized关键字修饰一个方法,这个方法同步执行。就是每次只能一个线程来执行。
- 普通的方法:对象调用。锁定的对象,就是this对象。
- 静态的方法:类调用。锁定的对象,就是类名.class
同步的原理:利用对象的互斥锁。
每个线程来访问,只能有一个线程进入执行,第一个动作锁对象(上锁)。来保证其他线程不能进入执行。等到该线程结束这个同步代码块或者同步方法,释放锁对象(开锁),才允许其他的线程来访问。
线程安全的类:
StringBuffer
Vector
HashTable
Collections,集合的工具类
2.2、线程之间的通信
线程之间的通信:wait(),notify(),notifyAll()
wait()——>让线程进入阻塞状态,暂停执行。一直阻塞
notify()——>唤醒线程,wait()住的线程,被唤醒。如果多个线程wait()了,唤醒其中的一个。
notifyAll()——>唤醒所有。
语法要求:必须在同步中,由同步的锁对象来调用。否则java.lang.IllegalMonitorStateException异常。
生产者消费者模型:
生产者(线程t1)负责生产产品,存入容器中(固定容量),消费者(线程t2)从容器中获取产品消费掉。
容器:
生产者:持有资源,生产产品,存入容器中
消费者:持有资源,消费掉产品。
容器满了:最多装8个鸡蛋
生产者:持有资源,暂停执行——直到容器还能继续装。
锁对象.wait()——>会让线程进入阻塞状态。暂停执行。notify(),notifyAll()
消费者:持有资源,直接消费。。
容器空了:最少0个。
生产者:持有资源,生产,存入。。
消费者:持有资源,暂停执行——直到容器中有产品
锁对象.wait()——>会让线程进入阻塞状态。暂停执行。notify(),notifyAll()
代码分析:
1、产品类:Egg()-->id
2、产生者:线程
cpu执行,run()-->生产鸡蛋,装入容器
3、消费者:线程
cpu执行,run()-->从容器中获取鸡蛋,吃掉(打印。。)
容器对象:
Class实现容器
数组: Egg[] arr = new Egg[8];
集合:栈,后进先出
同步的代码:
锁的是容器对象:
wait()和sleep()方法的区别:
- 出处不同:
- sleep()方法是Thread类中定义的。
- wait()方法是Object类中定义的。
- 解除阻塞的方式不同
- sleep()是时间到,自己醒。
- wait()方法等待被唤醒:notify(),或者是notifyAll()
- 对锁资源的释放情况
- sleep(),不释放
- wait(),释放