** 在Java中,synchronized关键字是用来控制线程同步的**
修饰方法
- 修饰一个方法
被修饰的方法为同步方法,作用的范围是整个方法
修饰代码块
被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象
- 锁一个对象
同一时间只允许同一线程操作该对象 - 锁一个类
其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象
很明显,锁住的是类时,不同的实例之间也会受影响,锁住的是实例对象时,只有同一实例才起作用。
等待和通知
在同步方法中,可以使用this.wait()使线程等待.
也可在其他线程使用this.notify()唤醒
生产者消费者案例
class Chicken{
int id;
public Chicken(int id) {
this.id = id;
}
}
class Cook implements Runnable{
SynContainer container;
public Cook(SynContainer container) {
this.container = container;
}
@Override
public void run() {
for (int i = 1; i < 100; i++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
container.push(new Chicken(i));
System.out.println("生产了"+i+"只鸡");
}
}
}
class Custom implements Runnable{
SynContainer container;
public Custom(SynContainer container) {
this.container = container;
}
@Override
public void run() {
for (int i = 1; i < 100; i++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("消费了 -->第"+container.pop().id+"只鸡");
}
}
}
class SynContainer{
Chicken[] chickens = new Chicken[10];
int count = 0;
public synchronized void push(Chicken chicken) {
//如果容器满了 ,等待消费者消费
if(count == chickens.length){
try {
//调用push方法的生产者进入等待状态,
System.out.println(Thread.currentThread().getName()+"发现盘子满了,等待顾客消费");
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//没满,丢入产品
chickens[count] = chicken;
count++;
//可以通知消费者消费了
System.out.println("通知消费者消费");
notify();
}
//消费者消费产品
public synchronized Chicken pop(){
//如果没有产品
if(count == 0){
// 等待生产者生产
try {
System.out.println(Thread.currentThread().getName()+"发现没有食物,等待厨子下厨");
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//可以消费
count--;
Chicken chicken = chickens[count];
notify();
return chicken;
}
}
public class WaitNotify {
public static void main(String[] args) {
SynContainer container = new SynContainer();
Custom custom = new Custom(container);
Cook cook = new Cook(container);
new Thread(cook,"厨子").start();
new Thread(custom,"顾客").start();
}
}