生产者和消费者关于锁的案例
程序员文章站
2022-03-08 22:38:34
...
1. 老版案例
public class tets2 {
public static void main(String[] args) {
Data data = new Data();
new Thread(()->{for(int i = 0 ;i<10;i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new Thread(()->{for(int i = 0 ;i<10;i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new Thread(()->{for(int i = 0 ;i<10;i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new Thread(()->{for(int i = 0 ;i<10;i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
/*生产者与消费者: 先有,再消费*/
class Data{
private int number = 0;
//生产者
public synchronized void increment() throws InterruptedException {
//只生产一个,只要还有,就先不创造
if(number != 0){
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName()+">="+number);
this.notifyAll();//唤醒其他线程
}
//消费者
public synchronized void decrement() throws InterruptedException {
//只要等于0,就等到去创造
if(number == 0) {
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName()+">="+number);
this.notifyAll();//唤醒其他线程
}
}
- increment 和 decrement 方法中的判断条件,得改成while循环,不然多个线程去操作同一个方法会出问题。
- 虚假唤醒
2.JUC版锁和监视器
public class tets3 {
public static void main(String[] args) {
Data2 data = new Data2();
new Thread(()->{for(int i = 0 ;i<10;i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(()->{for(int i = 0 ;i<10;i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"B").start();
new Thread(()->{for(int i = 0 ;i<10;i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"C").start();
new Thread(()->{for(int i = 0 ;i<10;i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"D").start();
}
}
/*生产者与消费者: 先有,再消费*/
class Data2{
private int number = 0;
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
//生产者
public void increment() throws InterruptedException {
try {
lock.lock();
//只生产一个,只要还有,就先不创造
while(number != 0){
condition.await();
}
number++;
System.out.println(Thread.currentThread().getName()+">="+number);
condition.signalAll();//唤醒其他线程
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
//消费者
public void decrement() throws InterruptedException {
try {
lock.lock();
//只要等于0,就等到去创造
while(number == 0) {
condition.await();
}
number--;
System.out.println(Thread.currentThread().getName()+">="+number);
condition.signalAll();//唤醒其他线程
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
- condition 的优势是,可以排序
打印案例
public class test4 {
public static void main(String[] args) {
Data4 data = new Data4();
new Thread(()->{for(int i = 0 ;i<10;i++) {
try {
data.printA();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(()->{for(int i = 0 ;i<10;i++) {
try {
data.printB();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"B").start();
new Thread(()->{for(int i = 0 ;i<10;i++) {
try {
data.printC();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"C").start();
}
}
/*打印案例: 通过number判断和多个监视器,实现顺序打印*/
class Data4{
int number = 1;
Lock lock = new ReentrantLock();
//一把锁可以创建多个监视器
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
Condition condition3 = lock.newCondition();
public void printA() throws InterruptedException {
try {
lock.lock();
//业务:判断》执行》通知
while(number != 1){
condition1.await();
}
System.out.println(Thread.currentThread().getName()+">="+"AAAA");
number = 2;
condition2.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printB() throws InterruptedException {
try {
lock.lock();
//业务:判断》执行》通知
while(number != 2){
condition2.await();
}
System.out.println(Thread.currentThread().getName()+">="+"BBBBB");
number = 3;
condition3.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printC() throws InterruptedException {
try {
lock.lock();
//业务:判断》执行》通知
while(number != 3){
condition3.await();
}
System.out.println(Thread.currentThread().getName()+">="+"CCCCCC");
number = 1;
condition1.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}