1、synchronized版本(判断等待、业务、通知)
1.1当有两条线程时
/**
* 线程之间的通信问题:生产和消费者问题 等待唤醒 通知唤醒
* 线程交替执行AB 操作同一个变量 num = 0
*/
public class TestPC {
public static void main(String[] args){
Data data = new Data();
new Thread(()->{ for (int i = 0; i < 5; i++)data.increment();},"A").start();
new Thread(()->{ for (int i = 0; i < 5; i++)data.decrement();},"B").start();
}
}
//等待,业务,通知
class Data{
private int num = 0;
//+1
public synchronized void increment(){
if(num != 0){//等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
num++;
System.out.println(Thread.currentThread().getName()+"->"+num);
//通知其他线程,我+1完成
this.notifyAll();
}
//-1
public synchronized void decrement(){
if(num == 0){//等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
num--;
System.out.println(Thread.currentThread().getName()+"->"+num);
//通知其他线程,我-1完成
this.notifyAll();
}
}
1.2当有4条线程时(虚假唤醒)
因此,将if判断改为while判断
2、Lock版本的生产者消费者
public class JUCTestPC {
public static void main(String[] args){
Data1 data = new Data1();
new Thread(()->{ for (int i = 0; i < 10; i++)data.increment();},"A").start();
new Thread(()->{ for (int i = 0; i < 10; i++)data.decrement();},"B").start();
new Thread(()->{ for (int i = 0; i < 10; i++)data.increment();},"C").start();
new Thread(()->{ for (int i = 0; i < 10; i++)data.decrement();},"D").start();
}
}
//等待,业务,通知
class Data1{
private int num = 0;
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
//+1
public void increment(){
lock.lock();
try {
while(num != 0){//等待
condition.await();
}
num++;
System.out.println(Thread.currentThread().getName()+"->"+num);
//通知其他线程,我+1完成
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
//-1
public void decrement(){
lock.lock();
try {
while(num == 0){//等待
condition.await();
}
num--;
System.out.println(Thread.currentThread().getName()+"->"+num);
//通知其他线程,我-1完成
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
3、Condition精确通知和唤醒线程
//多监视器实现,1:A 2:B 3:C
//精准唤醒某个监视器
public class JUCTestConditionPC {
public static void main(String[] args) {
Data3 data3 = new Data3();
new Thread(()->{ for (int i = 0; i < 5; i++) data3.printA(); },"A").start();
new Thread(()->{ for (int i = 0; i < 5; i++) data3.printB(); },"B").start();
new Thread(()->{ for (int i = 0; i < 5; i++) data3.printC(); },"C").start();
}
}
class Data3{
private int num = 1;
private Lock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
Condition condition3 = lock.newCondition();
public void printA(){
lock.lock();
try {
while(num!=1){
condition1.await();
}
num = 2;
System.out.println(Thread.currentThread().getName()+"->AAA");
condition2.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printB(){
lock.lock();
try {
while(num!=2){
condition2.await();
}
num = 3;
System.out.println(Thread.currentThread().getName()+"->BBB");
condition3.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printC(){
lock.lock();
try {
while(num!=3){
condition3.await();
}
num = 1;
System.out.println(Thread.currentThread().getName()+"->CCC");
condition1.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
4、八锁现象
Synchronized修饰的普通同步方法锁的是对象
static synchronized 锁的是一个class