生产者消费者实现一:
题:一个初始值为0的变量,两个线程对其交替执行,一个 +1,一个 -1,共执行5轮
注:多线程中的判断要用while
package com.ctgu.juc;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 生产者消费者模型
* 题:一个初始值为0的变量,两个线程对其交替执行,一个 +1,一个 -1,共执行5轮
*/
public class ProducerConsumer {
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();
}
}
//资源共享类
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();
}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();
}finally {
lock.unlock();
}
}
}
Synchronized和Lock的区别:
-
原始层面
synchronized是关键字,属于JVM层面
Lock是接口,属于API层面的锁
-
使用方法
synchronized不需要用户手动释放锁,当synchronized代码执行完后系统会自动让线程释放对锁的占用
Lock需要用户自己去释放锁,若没有主动释放锁,就有可能导致死锁的现象
-
等待是否可中断
synchronized不可中断,除非抛出异常或者正常运行完成
Lock可以中断
-
加锁是否公平
synchronized非公平锁
Lock两者都可以,默认非公平锁,构造方法传入boolean指定什么锁
-
锁绑定多个Condition
synchronized没有
Lock用来实现分组唤醒需要唤醒的线程,可以精确唤醒,而不是像synchronized随机唤醒一个或全部
生产者消费者实现二:
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
class ResourceData{
private volatile boolean flag = true;
private AtomicInteger atomicInteger = new AtomicInteger();
private BlockingQueue<String> blockingQueue = null;
public ResourceData(BlockingQueue<String> blockingQueue) {
this.blockingQueue = blockingQueue;
}
public void producer() throws InterruptedException {
boolean result;
String data = null;
while(flag){
data = atomicInteger.getAndIncrement()+"";
result = blockingQueue.offer(data,2L, TimeUnit.SECONDS);
if(result){
System.out.println(Thread.currentThread().getName()+" \t 插入队列成功 :" +data);
}else{
System.out.println(Thread.currentThread().getName()+" \t 插入队列失败");
}
TimeUnit.SECONDS.sleep(1);
}
System.out.println(Thread.currentThread().getName()+" \t 停止插入队列");
}
public void consumer() throws InterruptedException{
String data = null;
while(flag){
data = blockingQueue.poll(2l, TimeUnit.SECONDS);
System.out.println(Thread.currentThread().getName()+" \t 获取队列中的数据 : " +data);
TimeUnit.SECONDS.sleep(1);
}
}
public void stop(){
flag = false;
}
}
public class ProdConsumer {
public static void main(String[] args) throws InterruptedException {
ResourceData data = new ResourceData(new ArrayBlockingQueue<String>(10));
new Thread(()->{
try {
data.producer();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"producer").start();
new Thread(()->{
try {
data.consumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"consumer").start();
TimeUnit.SECONDS.sleep(5);
data.stop();
}
}