java 并发(2) 生产者和消费者问题的几种实现

有几种实现方法,一种是通过临界缓冲区的wait和notify来协调多个线程的并发,一种可以借用jdk 1.5+自带的BlockingQueue来实现,还有一种可以通过jdk1.5+的信号量机制来控制并发。

 

jdk1.5- 采用Object的wait 和notify方法来实现:

package com.xx.concurrent.commonUse;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.CountDownLatch;

import com.fangming.pub.StringUtils;

class Productor extends Thread {

	Queue<String> buffer;

	int quality;

	public Productor(Queue<String> buffer, int quality) {
		this.buffer = buffer;
		this.quality = quality;
	}

	@Override
	public void run() {
		try {
			product();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		ProductorAndCustomer.latch.countDown();
	}

	private void product() throws InterruptedException {
		synchronized (buffer) {
			while (quality > 0) {
				if (buffer.size() == ProductorAndCustomer.BUFFERSIZE) {
					buffer.wait();
				} else {
					String str = StringUtils.getRandomString(10);
					buffer.offer(str);
					quality--;
					System.out.println("####producer product " + str);
					buffer.notify();
				}
			}
		}
	}
}

class Customer extends Thread {

	Queue<String> buffer;
	int quality;

	public Customer(Queue<String> buffer, int quality) {
		this.buffer = buffer;
		this.quality = quality;
	}

	@Override
	public void run() {
		try {
			cusume();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		ProductorAndCustomer.latch.countDown();
	}

	private void cusume() throws InterruptedException {
		synchronized (buffer) {
			while (quality > 0) {
				if (buffer.size() == 0) {
					buffer.wait();
				} else {
					String str = buffer.poll();
					System.out.println("$$$$customer cocume " + str);
					quality--;
					buffer.notify();
				}
			}
		}
	}
}

public class ProductorAndCustomer {

	static final int BUFFERSIZE = 10;

	static CountDownLatch latch = new CountDownLatch(15);

	public static void main(String[] args) throws InterruptedException {

		long startTime = System.nanoTime();
		Queue<String> buffer = new LinkedList<String>();
		for (int i = 0; i < 10; i++) {
			Thread t1 = new Productor(buffer, 100);
			t1.start();
		}

		for (int i = 0; i < 5; i++) {
			Thread t2 = new Customer(buffer, 200);
			t2.start();
		}
		latch.await();
		long endTime = System.nanoTime();
		System.out.println(endTime - startTime);

	}

}

 

jdk1.5+ 采用BlockingQueue来实现

package com.xx.concurrent.commonUse;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch;


public class MutiProductorAndCustomer {
	
	ArrayBlockingQueue<String> buffer = new ArrayBlockingQueue<String>(5);
	
	static CountDownLatch latch = new CountDownLatch(15); 
	
	class Productor extends Thread {
		
		int quality;
		
		Productor(int quality){
			this.quality = quality;
		}
		
		@Override
		public void run(){
			while(quality > 0){
				try {
					product();
				} catch (InterruptedException e) {
					e.printStackTrace();
					quality++;
				}
				quality--;
			}
			latch.countDown();
		}
		
		public void product() throws InterruptedException{
			
			String str = StringUtils.getRandomString(10);
			buffer.put(str);
			System.out.println(this.getName() + " product " + str);
			
		}
	}
	
	class Customer extends Thread {
		
		int quality;
		
		Customer(int quality){
			this.quality = quality;
		}
		
		@Override
		public void run(){
			while(quality > 0){
				try {
					consume();
				} catch (InterruptedException e) {
					e.printStackTrace();
					quality++; 
				}
				quality--;
			}
			latch.countDown();
		}
		
		public void consume() throws InterruptedException{
			
			String str = buffer.take();
			System.out.println(this.getName() + " cusume " + str);
			
		}
	}
	
	/**
	 * @param args
	 * @throws InterruptedException 
	 */
	public static void main(String[] args) throws InterruptedException {
		long startTime = System.nanoTime();
		MutiProductorAndCustomer demo = new MutiProductorAndCustomer();
		for(int i =0 ; i< 10; i++){
			Thread t1 = demo.new Productor(100);
			t1.start();
		}
		
		for(int i =0 ; i< 5; i++){
			Thread t2 = demo.new Customer(200);
			t2.start();
		}
		latch.await();
		long endTime = System.nanoTime();
		System.out.println(endTime - startTime);
	}

}

 字符串随机生成器StringUtils

package com.xx.pub;

import java.util.Random;

public class StringUtils {

	public static String getRandomString(int length) { //length表示生成字符串的长度
	    String base = "abcdefghijklmnopqrstuvwxyz0123456789";   
	    Random random = new Random();   
	    StringBuffer sb = new StringBuffer();   
	    for (int i = 0; i < length; i++) {   
	        int number = random.nextInt(base.length());   
	        sb.append(base.charAt(number));   
	    }   
	    return sb.toString();   
	 } 
	
}

jdk 1.5+ 采用信号量实现 

使用了3个信号量,mutex用来控制对临界缓冲区的访问,slots标识空闲的缓冲区,items标识已装入的缓冲区。如果使用ConcurrentLinkedQueue做缓冲区的话,互斥信号量mutex可以不用。

 

package com.xx.concurrent.commonUse;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;


public class ProductorAndCustomerWithSemaphore {
	//此处使用的是非线程安全LinkedList
	Queue<String> buffer = new LinkedList<String>();
        //使用ConcurrentLinkedQueue的话,互斥信号量mutex可以不用,可以提高一定的性能
	//Queue<String> buffer = new ConcurrentLinkedQueue<String>();

	static int BUFFERSIZE = 10;
	
	//线程数量
	static CountDownLatch latch = new CountDownLatch(15); 
	
	static Semaphore mutex = new Semaphore(1);
	static Semaphore slots = new Semaphore(BUFFERSIZE);
	static Semaphore items = new Semaphore(0);
	
	class Productor extends Thread {
		
		int quality;
		
		Productor(int quality){
			this.quality = quality;
		}
		
		@Override
		public void run(){
			while(quality > 0){
				try {
					slots.acquire();
					mutex.acquire();
					product();
					mutex.release();
					items.release();
				} catch (InterruptedException e) {
					e.printStackTrace();
					quality++;
				}
				quality--;
			}
			latch.countDown();
		}
		
		public void product() throws InterruptedException{
			String str = StringUtils.getRandomString(10);
			buffer.offer(str);
			System.out.println(this.getName() + " product " + str);
			
		}
	}
	
	class Customer extends Thread {
		
		int quality;
		
		Customer(int quality){
			this.quality = quality;
		}
		
		@Override
		public void run(){
			while(quality > 0){
				try {
					items.acquire();
					mutex.acquire();
					consume();
					mutex.release();
					slots.release();
				} catch (InterruptedException e) {
					e.printStackTrace();
					quality++; 
				}
				quality--;
			}
			latch.countDown();
		}
		
		public void consume() throws InterruptedException{
			
			String str = buffer.poll();
			System.out.println(this.getName() + " cusume " + str);
			
		}
	}
	
	/**
	 * @param args
	 * @throws InterruptedException 
	 */
	public static void main(String[] args) throws InterruptedException {
		long startTime = System.nanoTime();
		ProductorAndCustomerWithSemaphore demo = new ProductorAndCustomerWithSemaphore();
		for(int i =0 ; i< 10; i++){
			Thread t1 = demo.new Productor(100);
			t1.start();
		}
		
		for(int i =0 ; i< 5; i++){
			Thread t2 = demo.new Customer(200);
			t2.start();
		}
		latch.await();
		long endTime = System.nanoTime();
		System.out.println(endTime - startTime);
	}
}
 

 

性能比较:

jdk1.5-  wait() & notify()
111658991ns

jdk1.5+  ArrayBlockingQueue
98588747ns 

jdk1.5+  Semaphore 使用线程不安全的buffer  linkedList
123800982ns 

jdk1.5+  Semaphore 使用线程不安全的buffer  ConcurrentLinkedQueue
110885827ns

 

可以看出使用BlockQueue来实现生产者和消费者问题,性能最好。

 

你可能感兴趣的:(java)