一、生产者消费者模型实现
1. wait/notify/notifyAll实现
注意线程中的判断使用while判断,不用if判断!
public class ConsumerAndProductor {
final LinkedList<Integer> container = new LinkedList();
final static int MAX = 10;
static int size;// 容量
public int getCount() {
return size;
}
public synchronized void pruduct() {
while (getCount() == MAX) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 不成立的话
size++;
container.add(size);
System.out.println("container has producted 1, size=" + size);
this.notifyAll();
}
public synchronized void consumer() {
// 生产者要与消费者配套执行,否则不可执行
while (getCount() == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
size--;
container.removeFirst();// 消费一个
System.out.println("container has consumerd 1, size=" + size);
this.notifyAll();
}
public static void main(String[] args) {
ConsumerAndProductor cp = new ConsumerAndProductor();
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
cp.consumer();
}
}
}).start();
}
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 2; i++) {
new Thread(new Runnable() {
@Override
public void run() {
for (int j = 0; j < 25; j++) {
cp.pruduct();
}
}
}).start();
}
}
}
2. await/signal/signalAll
主要是利用JUC中的Condition条件来实现定点通知。
public class ConsumerAndProductII {
final LinkedList<Integer> container = new LinkedList<>();
final Lock lock = new ReentrantLock();
final Condition consumerCondition = lock.newCondition();
final Condition producterCondition = lock.newCondition();
final static int MAX = 10;
static int size;// 容量
public int getCount() {
return size;
}
public void product() {
// 生产者
try {
// 获取到当前锁
lock.lock();
while (this.getCount() == MAX) {
try {
// 到达最大的容量就不生产
producterCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
size++;
int anInt = new Random().nextInt(100);
System.out.println("生产者生产产品:" + anInt);
container.add(anInt);
// 这样的话,可以实现定点推送任务
consumerCondition.signal();
} finally {
// 释放锁
lock.unlock();
}
}
public void consumer() {
// 生产者
try {
// 获取到当前锁
lock.lock();
while (this.getCount() == 0) {
try {
// 到达最大的容量就不生产
consumerCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
size--;
Integer remove = container.remove();
System.out.println("消费者消费产品:" + remove);
// 这样的话,可以实现定点推送任务
producterCondition.signal();
} finally {
// 释放锁
lock.unlock();
}
}
public static void main(String[] args) {
ConsumerAndProductII cp = new ConsumerAndProductII();
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
cp.consumer();
}
}
}).start();
}
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 2; i++) {
new Thread(new Runnable() {
@Override
public void run() {
for (int j = 0; j < 25; j++) {
cp.product();
}
}
}).start();
}
}
}
3. 利用BlockingQueue来实现
主要是利用ArrayBlockingQueue阻塞队列来实现。
class MyResouce {
// 标志位
private volatile boolean FLAG = true;
// 运算的原子类
private AtomicInteger atomicInteger = new AtomicInteger();
// 阻塞队列
private BlockingQueue<String> blockingQueue = null;
// 阻塞队列是不定的,在构造器中传入可以适应多样的阻塞队列
public MyResouce(BlockingQueue<String> blockingQueue) {
this.blockingQueue = blockingQueue;
System.out.println(blockingQueue.getClass().getName());
}
public void prod() {
String data = null;
boolean retValue;
// 为真的时候,此时生产
while (FLAG) {
// 获取生产的数据
data = atomicInteger.incrementAndGet() + "";
try {
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 插入队列失败");
}
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "\t 主线程叫停了,停止生产,FLAG=false");
}
public void consume() {
String result = null;
while (FLAG) {
try {
result = blockingQueue.poll(2L, TimeUnit.SECONDS);
if (result == null || result.equalsIgnoreCase("")) {
FLAG = false;
System.out.println(Thread.currentThread().getName() + "\t 超过2秒钟没有发现有产品可消费,消费退出.....");
System.out.println();
System.out.println();
return;
}
System.out.println(Thread.currentThread().getName() + "\t 消费产品" + result + "成功!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void stop() {
this.FLAG = false;
}
}
public class ConsumerAndProductIII {
public static void main(String[] args) {
MyResouce myResouce = new MyResouce(new ArrayBlockingQueue<>(10));
new Thread(() -> {
System.out.println("生产者线程启动!");
myResouce.prod();
}, "Product").start();
new Thread(() -> {
System.out.println("消费者线程启动!");
System.out.println();
System.out.println();
myResouce.consume();
}, "Consume").start();
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println();
System.out.println();
System.out.println();
System.out.println("5秒钟时间到,主线程叫停!");
myResouce.stop();
}
}
4. 总结
记住:线程 操作 资源类!