回顾java多线程安全这一part的时候,再学到生产者与消费者的问题。因此写一博客进行记录,同时希望能给在看博客的你提供一些帮助。
这篇文章主要介绍如何通过
- synchronized加锁的方式
- lock&&Condition的方式
- lock&&Condition精准通知与唤醒的方式来实现生产者和消费者
这三种方式属于层层优化,且都是简单案例,读者可以在此基础上进行扩展。
实现生产者和消费者的主要思路和步骤
- 判断等待
- 执行业务
- 通知唤醒
场景:
某线程生产一件物品,当该物品被消耗完时才会继续生产;同时另一线程消耗某件物品,当该物品数量大于零时才会继续消耗。通俗来说,就是生产一件物品与消耗一件物品有序交替执行。为了保证物品数量的线程安全,我们需要加锁。
方式一:synchronized
说明:该方式选择在资源类Data的生产和消费方法上加上synchronized从而声明为同步方法。这种方式不推荐。
Data类为资源类,提供生产和消费的方法。对于生产方法来说,当不满足生产条件时,进入等待状态,在判断满足生产的条件下会执行生产业务,同时唤醒消费者进行消费。对于消费方法来说,当不满足消费条件时,进入等待状态,在判断满足消费的条件下会执行消费业务,同时唤醒生产者进行生产。
public class ProductDemo {
public static void main(String[] args) {
Data data = new Data();
new Thread(()->{
for(int i=0;i<4;i++){
data.increase();
}
},"A").start();
new Thread(()->{
for(int i=0;i<4;i++){
data.increase();
}
},"B").start();
new Thread(()->{
for(int i=0;i<4;i++){
data.decrease();
}
},"C").start();
new Thread(()->{
for(int i=0;i<4;i++){
data.decrease();
}
},"D").start();
}
}
//判断等待;业务;通知
class Data{
private int num=0;
public synchronized void increase(){
while (num!=0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
num++;
System.out.println(Thread.currentThread().getName()+"==>"+num);
this.notifyAll();
}
public synchronized void decrease(){
while (num==0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
num--;
System.out.println(Thread.currentThread().getName()+"==>"+num);
this.notifyAll();
}
}
方式二:lock&&Condition的普通方式
说明:Condition是java.util.concurrent.locks下的接口,基本的方法就是await()和signal()方法;Condition依赖于Lock接口,生成一个Condition的基本代码是lock.newCondition(),调用Condition的await()和signal()方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使用。
public class NewProductDemo {
public static void main(String[] args) {
Data2 data = new Data2();
new Thread(()->{
for(int i=0;i<4;i++){
data.increase();
}
},"A").start();
new Thread(()->{
for(int i=0;i<4;i++){
data.increase();
}
},"B").start();
new Thread(()->{
for(int i=0;i<4;i++){
data.decrease();
}
},"C").start();
new Thread(()->{
for(int i=0;i<4;i++){
data.decrease();
}
},"D").start();
}
}
//判断等待;业务;通知
class Data2{
private int num=0;
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
public void increase(){
lock.lock();
try {
while (num!=0) {
condition.await();
}
num++;
System.out.println(Thread.currentThread().getName()+"==>"+num);
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void decrease(){
lock.lock();
try {
while (num==0) {
condition.await();
}
num--;
System.out.println(Thread.currentThread().getName()+"==>"+num);
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
方式三:lock&&Condition的精准通知与唤醒
说明:由于某些场景下我们要考虑到多个任务的顺序执行,或者需要精准唤醒指定方法,可以考虑使用这种方式。
public class LatestProductDemo {
public static void main(String[] args) {
Data3 data = new Data3();
new Thread(()->{
for(int i=0;i<4;i++){
data.showA();
}
},"A").start();
new Thread(()->{
for(int i=0;i<4;i++){
data.showB();
}
},"B").start();
new Thread(()->{
for(int i=0;i<4;i++){
data.showC();
}
},"C").start();
}
}
//判断等待;业务;通知
class Data3{
private int num=1;
Lock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
Condition condition3 = lock.newCondition();
public void showA(){
lock.lock();
try {
while (num!=1) {
condition1.await();
}
num=2;
System.out.println(Thread.currentThread().getName()+"==>"+num);
condition2.signal();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void showB(){
lock.lock();
try {
while (num!=2) {
condition2.await();
}
num=3;
System.out.println(Thread.currentThread().getName()+"==>"+num);
condition3.signal();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void showC(){
lock.lock();
try {
while (num!=3) {
condition3.await();
}
num=1;
System.out.println(Thread.currentThread().getName()+"==>"+num);
condition1.signal();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
最近一看,被自动设置为VIP文章了,感觉不方便大家学习,于因此取消掉了VIP观看。
觉得不错可以点赞或关注哟~