思路分析:
1、两个线程、一个生产、一个消费,要保证可见性,所以需要volatile
2、多线程下要保证原子性,所以生产消费的数据用IAtomicnteger
3、使用那种阻塞队列需要依赖传入的参数来决定,所以构造传接口进来
4、使用阻塞队列中包含超时的offer、poll
代码实现:
/**
* @title: MyResource
* @description: 实现生产-消费者
* @author:quLiangquan
* @date 2019/8/16 16:22
**/
//资源类
public class MyResource {
private volatile boolean FLAG = true;
private AtomicInteger atomicInteger = new AtomicInteger();
private BlockingQueue<String> blockingQueue = null;
//构造方法
public MyResource(BlockingQueue<String> blockingQueue) {
this.blockingQueue = blockingQueue;
}
public void myProd() throws Exception {
String data = null;
boolean res;
while (FLAG) {
data = atomicInteger.incrementAndGet() + "";
res = blockingQueue.offer(data, 2L, TimeUnit.SECONDS);
if (res) {
System.out.println(Thread.currentThread().getName() + " 写入 " + data + " 成功");
} else {
System.out.println(Thread.currentThread().getName() + " 写入 " + data + " 失败");
}
TimeUnit.SECONDS.sleep(1);
}
System.out.println(Thread.currentThread().getName() + " 叫停了、不生产了");
}
public void myConsumer() throws Exception {
String res = null;
while (FLAG) {
res = blockingQueue.poll(2, TimeUnit.SECONDS);
if (null == res || res.equalsIgnoreCase("")) {
FLAG = false;
System.out.println(Thread.currentThread().getName() + " 超过2秒没取到数据、退出消费");
return; //停止
}
System.out.println(Thread.currentThread().getName() + " 消费 " + res + " 成功");
}
}
public void stop() {
this.FLAG = false;
}
public static void main(String[] args) throws Exception{
//资源类
MyResource myResource = new MyResource(new ArrayBlockingQueue<>(10));
//线程操作资源类
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " 生产线程启动");
try {
myResource.myProd();
} catch (Exception e) {
e.printStackTrace();
}
},"Prod" ).start();
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " 消费线程启动");
try {
myResource.myConsumer();
} catch (Exception e) {
e.printStackTrace();
}
},"Consumer" ).start();
TimeUnit.SECONDS.sleep(5);
System.out.println("叫停");
myResource.stop();
}
}