一、利用阻塞队列
import java.util.List;
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class ProducerConsumerByBlockingQueue {
private static BlockingQueue<String> queue = new ArrayBlockingQueue<>(5);
private volatile static boolean isRunning=true;
private static final int SIZE=5;
private static Random r=new Random();
private static class Producer extends Thread
{
@Override
public void run() {
while (isRunning){
try{
Thread.sleep(r.nextInt(1000));
queue.put("producer");
}catch (InterruptedException ie)
{
ie.printStackTrace();
}
System.out.println("producer");
}
}
}
private static class Consumer extends Thread
{
@Override
public void run() {
while (isRunning)
{
try{
Thread.sleep(r.nextInt(1000));
queue.take();
}catch (InterruptedException ie){
ie.printStackTrace();
}
System.out.println("consumer");
}
}
}
public static void main(String[] args) {
for(int i=0;i<2;i++)
{
Thread producer=new ProducerConsumerByBlockingQueue.Producer();
producer.start();
}
for(int i=0;i<10;i++)
{
Thread consumer=new ProducerConsumerByBlockingQueue.Consumer();
consumer.start();
}
for(int i=0;i<3;i++)
{
Thread producer=new ProducerConsumerByBlockingQueue.Producer();
producer.start();
}
}
}
二、利用信号量
package Concurrency;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Semaphore;
public class ProducerConsumerBySemaphore {
private static Semaphore consumer_mutex= new Semaphore(0);
private static Semaphore producer_mutex= new Semaphore(5);
private volatile static boolean isRunning=true;
private static List<String> list=new CopyOnWriteArrayList<>();
private static final int SIZE=5;
private static Random r=new Random();
private static class Producer extends Thread{
@Override
public void run() {
try{
while (isRunning)
{
Thread.sleep(r.nextInt(1000));
producer_mutex.acquire(1);
Thread.sleep(1);
list.add("producer");
}
}catch (InterruptedException ie)
{
ie.printStackTrace();
}finally {
consumer_mutex.release(1);
System.out.println("producer");
}
}
}
private static class Consumer extends Thread{
@Override
public void run() {
try {
while (isRunning)
{
Thread.sleep(r.nextInt());
consumer_mutex.acquire(1);
Thread.sleep(1);
list.remove(0);
}
}catch (InterruptedException ie)
{
ie.printStackTrace();
}finally {
producer_mutex.release(1);
System.out.println("consumer");
}
}
}
public static void main(String[] args) {
for(int i=0;i<2;i++)
{
Thread producer= new ProducerConsumerBySemaphore.Producer();
producer.start();
}
for(int i=0;i<10;i++)
{
Thread consumer=new ProducerConsumerBySemaphore.Consumer();
consumer.start();
}
for(int i=0;i<3;i++)
{
Thread producer=new ProducerConsumerBySemaphore.Producer();
producer.start();
}
}
}
利用Synchronized
package Concurrency;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
public class ProducerConsumerBySynchronized {
private volatile static boolean isRunning=true;
private static List<String> list=new CopyOnWriteArrayList<>();
private static final int SIZE=5;
private static Random r=new Random();
private static class Producer extends Thread{
@Override
public void run() {
try{
while (isRunning)
{
Thread.sleep(r.nextInt(1000));
while (list.size()==SIZE)
{
synchronized (list)
{
System.out.println("Queue is full, producer "+Thread.currentThread().getId()+
"is waiting, size: "+list.size());
list.wait();
}
}
synchronized (list)
{
if(list.size()<SIZE)//双重检查
{
list.add("producer");
System.out.println("producer");
list.notifyAll();
}
}
}
}catch (InterruptedException ie)
{
ie.printStackTrace();
}
}
}
private static class Consumer extends Thread {
@Override
public void run() {
try{
while (isRunning)
{
Thread.sleep(r.nextInt(1000));
while (list.size()==0)
{
synchronized (list)
{
System.out.println("queue is Empty, consume "+Thread.currentThread().getId()
+" is waiting, size= "+list.size());
list.wait();
}
}
synchronized (list)
{
if(list.size()!=0)//类似于DCL,不加的话会出问题
{
list.remove(0);
System.out.println("consumer");
list.notifyAll();
}
}
}
}catch (InterruptedException ie)
{
ie.printStackTrace();
}
}
}
public static void stop()
{
isRunning=false;
}
public static void main(String[] args) {
for(int i=0;i<2;i++)
{
Thread producer= new ProducerConsumerBySynchronized.Producer();
producer.start();
}
for(int i=0;i<10;i++)
{
Thread consumer=new ProducerConsumerBySynchronized.Consumer();
consumer.start();
}
for(int i=0;i<3;i++)
{
Thread producer=new ProducerConsumerBySynchronized.Producer();
producer.start();
}
}
}
总结
所谓的并发不安全指的是在并发情况下可能会发生错误,上述的所有代码仅仅经过了我自己的简单测试,并不能保证绝对不出问题。同时,还有一种利用管程的方式实现待补充。