设计一个有界阻塞队列:
(1)多线程写入队列,当队列满时不能再写入数据;
(2)单线程读取数据,当队列为空时不能读取数据;
(3)读取超过一定时长则运行结束。
一、Synchronized锁实现
package com.fuping3.proandcon;
import java.util.LinkedList;
public class ListQueue{
private LinkedList<String> list=new LinkedList<String>();
private volatile int cap=0;
public ListQueue(int cap){
this.cap=cap;
}
public void entraList(String str){
synchronized (list){
while(list.size()>=cap){
System.out.println(Thread.currentThread().getName()+"阻塞");
try {
list.wait();
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()+"中断");
e.printStackTrace();
}
}
list.addFirst(str);
System.out.println(Thread.currentThread().getName()+"放入数据:"+str);
list.notifyAll();
}
}
public void popList(){
String str="";
boolean breakFlag=false;
long now=System.currentTimeMillis();
synchronized (list){
while(list.isEmpty()){
long end=System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"阻塞");
try {
list.wait(1000*5);
if(end-now>1000){
breakFlag=true;
break;
}
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()+"中断");
e.printStackTrace();
}
}
if(!breakFlag){
str=list.removeLast();
System.out.println(Thread.currentThread().getName()+"消费数据:"+str);
list.notifyAll();
}
}
}
}
二、Lock锁实现
package com.fuping3.proandcon;
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class ListQueueWithAwait{
ReentrantLock lock=new ReentrantLock();
Condition c=lock.newCondition();
private LinkedList<String> list=new LinkedList<String>();
private volatile int cap=0;
public ListQueueWithAwait(int cap){
this.cap=cap;
}
public void entraList(String str){
lock.lock();
try {
while(list.size()>=cap){
System.out.println(Thread.currentThread().getName()+"阻塞");
try {
c.await();
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()+"中断");
e.printStackTrace();
}
}
list.addFirst(str);
System.out.println(Thread.currentThread().getName()+"放入数据:"+str);
c.signalAll();
}finally {
lock.unlock();
}
}
public void popList(){
String str="";
boolean breakFlag=false;
long now=System.currentTimeMillis();
lock.lock();
try{
while(list.isEmpty()){
long end=System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"阻塞");
try {
c.await(1000*5, TimeUnit.MILLISECONDS);
if(end-now>1000){
breakFlag=true;
break;
}
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()+"中断");
e.printStackTrace();
}
}
if(!breakFlag){
str=list.removeLast();
System.out.println(Thread.currentThread().getName()+"消费数据:"+str);
c.signalAll();
}
}finally {
lock.unlock();
}
}
}
三、测试代码
package com.fuping3.proandcon;
public class ProducerAndConsumer {
private static Thread t1,t2;
public static void main(String[] args) {
//ListQueue list=new ListQueue(5);
ListQueueWithAwait list=new ListQueueWithAwait(5);
new Thread(()->{
int i=1;
while(i<=5){
list.entraList("message"+i);
i++;
}
},"p1").start(); new Thread(()->{
int i=1;
while(i<=5){
list.entraList("message"+i);
i++;
}
},"p2").start();
new Thread(()->{
int i=1;
while(i<=5){
list.entraList("message"+i);
i++;
}
},"p3").start();
new Thread(()->{
int i=1;
while(i<=16){
list.popList();
i++;
}
},"c1").start();
}
}
四、运行结果
p1放入数据:message1
p1放入数据:message2
p1放入数据:message3
p1放入数据:message4
p1放入数据:message5
p2阻塞
p3阻塞
c1消费数据:message1
c1消费数据:message2
c1消费数据:message3
c1消费数据:message4
c1消费数据:message5
c1阻塞
p2放入数据:message1
p2放入数据:message2
p2放入数据:message3
p2放入数据:message4
p2放入数据:message5
p3阻塞
c1消费数据:message1
c1消费数据:message2
c1消费数据:message3
c1消费数据:message4
c1消费数据:message5
c1阻塞
p3放入数据:message1
p3放入数据:message2
p3放入数据:message3
p3放入数据:message4
p3放入数据:message5
c1消费数据:message1
c1消费数据:message2
c1消费数据:message3
c1消费数据:message4
c1消费数据:message5
c1阻塞
c1阻塞