摘要
本博文主要是介绍多线程中的实战问题。通过实际的代码和例子提供大家更多练习和学习以及参考。
模拟多消费者和多生产者的的产生和消费问题
使用的锁的代码
package com.zhuangxiaoyan.jdk.juc.JucLock;
import java.time.LocalDate;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @Classname ProducerSumer
* @Description
* @Date 2021/11/27 7:59
* @Created by xjl
*/
class ShareData{
private int number=0;
private Lock lock=new ReentrantLock();
private Condition condition=lock.newCondition();
public void increment()throws Exception{
lock.lock();
try {
//判断
while (number!=0){
//等待 不能生产
condition.await();
}
//干活
number++;
System.out.println(Thread.currentThread().getName()+"\t"+number);
//通知唤醒
condition.signalAll();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void decrement()throws Exception{
lock.lock();
try {
//判断
while (number==0){
//等待 不能生产
condition.await();
}
//干活
number--;
System.out.println(Thread.currentThread().getName()+"\t"+number);
//通知唤醒
condition.signalAll();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
public class ProducerSumer {
public static void main(String[] args) {
ShareData shareData=new ShareData();
new Thread(()->{
for (int i=1;i<=5;i++){
try {
shareData.increment();
} catch (Exception e) {
e.printStackTrace();
}
}
},"AAA").start();
new Thread(()->{
for (int i=1;i<=5;i++){
try {
shareData.decrement();
} catch (Exception e) {
e.printStackTrace();
}
}
},"BBB").start();
}
}
使用原子类和volatile实现
package com.zhuangxiaoyan.jdk.juc.JucLock;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @Classname MQDemo
* @Description TODO
* @Date 2021/11/27 8:45
* @Created by xjl
*/
class MyResource {
private volatile Boolean FLAG = true;//默认开启生产和消费
private AtomicInteger atomicInteger = new AtomicInteger();
BlockingQueue<String> blockingQueue = null;
//构造函数
public MyResource(BlockingQueue<String> blockingQueue) {
this.blockingQueue = blockingQueue;
System.out.println(blockingQueue.getClass().getName());
}
public void Producer() throws Exception {
String data = null;
boolean retvalue;
while (FLAG) {
data = atomicInteger.incrementAndGet() + "";
retvalue = blockingQueue.offer(data, 2L, TimeUnit.SECONDS);
if (retvalue) {
System.out.println(Thread.currentThread().getName() + "\t插入队列" + data + "成功");
} else {
System.out.println(Thread.currentThread().getName() + "\t插入队列" + data + "失败");
}
TimeUnit.SECONDS.sleep(1);
}
System.out.println(Thread.currentThread().getName() + "\t大老板叫停了,表示FLAG=false,生产动作结束\n");
}
public void Consumer() throws Exception {
String result = null;
while (FLAG) {
result = blockingQueue.poll(2L, TimeUnit.SECONDS);
if (null == result || result.equalsIgnoreCase("")) {
FLAG = false;
System.out.println(Thread.currentThread().getName() + "\t 超时没有消费任务 消费退出");
return;
}
System.out.println(Thread.currentThread().getName() + "\t消费队列" + result + "成功");
}
}
public void stop() {
this.FLAG = false;
}
}
public class MQDemo {
public static void main(String[] args) throws InterruptedException {
MyResource myResource = new MyResource(new ArrayBlockingQueue<>(10));
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t生产线程启动……");
try {
myResource.Producer();
} catch (Exception e) {
e.printStackTrace();
}
}, "生产线程").start();
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t消费线程启动……");
try {
myResource.Consumer();
} catch (Exception e) {
e.printStackTrace();
}
}, "消费线程").start();
TimeUnit.SECONDS.sleep(5);
System.out.println("停止生产和消费的过程……");
myResource.stop();
}
}
模拟多线程的顺序调用
多线程之间按顺序调用,实现A->B->C三个线程启动,要求如下: AA打E印5次,BB打印10次,CC打E15次。
package com.zhuangxiaoyan.jdk.juc.JucLock;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @Classname ReentrantLockDemo
* @Description 多线程之间按顺序调用,实现A->B->C三个线程启动,要求如下: AA打E印5次,BB打印10次,CC打E15次
* @Date 2021/11/27 8:21
* @Created by xjl
*/
class ShareResource{
private int number=1;
private Lock lock=new ReentrantLock();
private Condition c1=lock.newCondition();
private Condition c2=lock.newCondition();
private Condition c3=lock.newCondition();
public void printA(){
lock.lock();
try {
//判断
while (number!=1){
c1.await();
}
//干活
for (int i=1;i<=5;i++){
System.out.println(Thread.currentThread().getName()+"\t"+i);
}
//通知
number=2;
c2.signal();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void printB(){
lock.lock();
try {
//判断
while (number!=2){
c2.await();
}
//干活
for (int i=1;i<=10;i++){
System.out.println(Thread.currentThread().getName()+"\t"+i);
}
//通知
number=3;
c3.signal();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void printC(){
lock.lock();
try {
//判断
while (number!=3){
c3.await();
}
//干活
for (int i=1;i<=15;i++){
System.out.println(Thread.currentThread().getName()+"\t"+i);
}
//通知
number=1;
c1.signal();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
public class ReentrantLockDemo {
public static void main(String[] args) {
ShareResource shareResource=new ShareResource();
new Thread(()->{
for (int i=1;i<=10;i++){
shareResource.printA();
}
},"AAA").start();
new Thread(()->{
for (int i=1;i<=10;i++){
shareResource.printB();
}
},"BBB").start();
new Thread(()->{
for (int i=1;i<=10;i++){
shareResource.printC();
}
},"CCC").start();
}
}