Java 使用队列的生产者/消费者线程
我想创建一些Java 使用队列的生产者/消费者线程,java,multithreading,queue,producer-consumer,Java,Multithreading,Queue,Producer Consumer,我想创建一些生产者/消费者线程应用程序。但我不确定在两者之间实现队列的最佳方式是什么 所以我有两个想法(这两个想法可能都是完全错误的)。我想知道哪一个更好,如果它们都很糟糕,那么实现队列的最佳方式是什么。我关心的主要是这些示例中队列的实现。我正在扩展一个队列类,它是内部类,是线程安全的。下面是两个示例,每个示例有4个类 主类- public class SomeApp { private Consumer consumer; private Producer producer;
生产者/消费者线程应用程序。但我不确定在两者之间实现队列的最佳方式是什么
所以我有两个想法(这两个想法可能都是完全错误的)。我想知道哪一个更好,如果它们都很糟糕,那么实现队列的最佳方式是什么。我关心的主要是这些示例中队列的实现。我正在扩展一个队列类,它是内部类,是线程安全的。下面是两个示例,每个示例有4个类
主类-
public class SomeApp
{
private Consumer consumer;
private Producer producer;
public static void main (String args[])
{
consumer = new Consumer();
producer = new Producer();
}
}
public class SomeApp
{
Queue<Object> readQ;
private Consumer consumer;
private Producer producer;
public static void main (String args[])
{
readQ = new Queue<Object>(100);
consumer = new Consumer(readQ);
producer = new Producer(readQ);
}
}
消费阶层-
public class Consumer implements Runnable
{
public Consumer()
{
Thread consumer = new Thread(this);
consumer.start();
}
public void run()
{
while(true)
{
//get an object off the queue
Object object = QueueHandler.dequeue();
//do some stuff with the object
}
}
}
public class Consumer implements Runnable
{
Queue<Object> queue;
public Consumer(Queue<Object> readQ)
{
queue = readQ;
Thread consumer = new Thread(this);
consumer.start();
}
public void run()
{
while(true)
{
//get an object off the queue
Object object = queue.dequeue();
//do some stuff with the object
}
}
}
生产者阶级-
public class Producer implements Runnable
{
public Producer()
{
Thread producer = new Thread(this);
producer.start();
}
public void run()
{
while(true)
{
//add to the queue some sort of unique object
QueueHandler.enqueue(new Object());
}
}
}
public class Producer implements Runnable
{
Queue<Object> queue;
public Producer(Queue<Object> readQ)
{
queue = readQ;
Thread producer = new Thread(this);
producer.start();
}
public void run()
{
while(true)
{
//add to the queue some sort of unique object
queue.enqueue(new Object());
}
}
}
队列类-
public class QueueHandler
{
//This Queue class is a thread safe (written in house) class
public static Queue<Object> readQ = new Queue<Object>(100);
public static void enqueue(Object object)
{
//do some stuff
readQ.add(object);
}
public static Object dequeue()
{
//do some stuff
return readQ.get();
}
}
//the extended Queue class is a thread safe (written in house) class
public class QueueHandler extends Queue<Object>
{
public QueueHandler(int size)
{
super(size); //All I'm thinking about now is McDonalds.
}
public void enqueue(Object object)
{
//do some stuff
readQ.add();
}
public Object dequeue()
{
//do some stuff
return readQ.get();
}
}
公共类队列处理程序
{
//此队列类是线程安全(内部编写)类
公共静态队列readQ=新队列(100);
公共静态void排队(对象)
{
//做点什么
readQ.add(对象);
}
公共静态对象出列()
{
//做点什么
返回readQ.get();
}
}
或
主类-
public class SomeApp
{
private Consumer consumer;
private Producer producer;
public static void main (String args[])
{
consumer = new Consumer();
producer = new Producer();
}
}
public class SomeApp
{
Queue<Object> readQ;
private Consumer consumer;
private Producer producer;
public static void main (String args[])
{
readQ = new Queue<Object>(100);
consumer = new Consumer(readQ);
producer = new Producer(readQ);
}
}
公共类SomeApp
{
队列读取;
私人消费者;
私营生产者;
公共静态void main(字符串参数[])
{
readQ=新队列(100);
消费者=新消费者(readQ);
生产者=新生产者(readQ);
}
}
消费阶层-
public class Consumer implements Runnable
{
public Consumer()
{
Thread consumer = new Thread(this);
consumer.start();
}
public void run()
{
while(true)
{
//get an object off the queue
Object object = QueueHandler.dequeue();
//do some stuff with the object
}
}
}
public class Consumer implements Runnable
{
Queue<Object> queue;
public Consumer(Queue<Object> readQ)
{
queue = readQ;
Thread consumer = new Thread(this);
consumer.start();
}
public void run()
{
while(true)
{
//get an object off the queue
Object object = queue.dequeue();
//do some stuff with the object
}
}
}
公共类使用者实现可运行
{
排队;
公共消费者(队列读取)
{
队列=readQ;
线程消费者=新线程(此);
consumer.start();
}
公开募捐
{
while(true)
{
//从队列中获取对象
Object Object=queue.dequeue();
//用这个物体做些东西
}
}
}
生产者阶级-
public class Producer implements Runnable
{
public Producer()
{
Thread producer = new Thread(this);
producer.start();
}
public void run()
{
while(true)
{
//add to the queue some sort of unique object
QueueHandler.enqueue(new Object());
}
}
}
public class Producer implements Runnable
{
Queue<Object> queue;
public Producer(Queue<Object> readQ)
{
queue = readQ;
Thread producer = new Thread(this);
producer.start();
}
public void run()
{
while(true)
{
//add to the queue some sort of unique object
queue.enqueue(new Object());
}
}
}
公共类生成器实现可运行
{
排队;
公共制作人(队列读取)
{
队列=readQ;
线程生成器=新线程(此线程);
producer.start();
}
公开募捐
{
while(true)
{
//向队列中添加某种独特的对象
排队(新对象());
}
}
}
队列类-
public class QueueHandler
{
//This Queue class is a thread safe (written in house) class
public static Queue<Object> readQ = new Queue<Object>(100);
public static void enqueue(Object object)
{
//do some stuff
readQ.add(object);
}
public static Object dequeue()
{
//do some stuff
return readQ.get();
}
}
//the extended Queue class is a thread safe (written in house) class
public class QueueHandler extends Queue<Object>
{
public QueueHandler(int size)
{
super(size); //All I'm thinking about now is McDonalds.
}
public void enqueue(Object object)
{
//do some stuff
readQ.add();
}
public Object dequeue()
{
//do some stuff
return readQ.get();
}
}
//扩展队列类是线程安全(内部编写)类
公共类QueueHandler扩展了队列
{
公共队列处理程序(整数大小)
{
超级(大);//我现在想的就是麦当劳。
}
公共无效排队(对象)
{
//做点什么
readQ.add();
}
公共对象出列()
{
//做点什么
返回readQ.get();
}
}
走吧 你正在重新发明轮子。
如果您需要持久性和其他企业特性,请使用(我建议)
如果需要快速内存队列,请使用java的一种实现
如果您需要支持java 1.4或更早版本,请使用Doug Lea的优秀软件包。java 5+提供了实现这类功能所需的所有工具。您将希望:
把你所有的制作人放在一起李>
将您的所有消费者放在另一个执行器服务中
李>
如有必要,在两人之间使用电话进行通信
我对(3)说“如果必要”,因为根据我的经验,这是一个不必要的步骤。您所要做的就是向consumer executor服务提交新任务。因此:
final ExecutorService producers = Executors.newFixedThreadPool(100);
final ExecutorService consumers = Executors.newFixedThreadPool(100);
while (/* has more work */) {
producers.submit(...);
}
producers.shutdown();
producers.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
consumers.shutdown();
consumers.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
因此,生产者
直接提交给消费者
好的,正如其他人所指出的,最好使用java.util.concurrent
包。我强烈推荐“实践中的Java并发”。这是一本很棒的书,几乎涵盖了你需要知道的一切
至于您的特定实现,正如我在评论中指出的,不要从构造函数启动线程——这可能是不安全的
撇开这一点不谈,第二种实现似乎更好。您不希望将队列放在静态字段中。你可能只是无缘无故地失去了灵活性
如果您想继续自己的实现(我想是为了学习?),请至少提供一个start()
方法。您应该构造对象(您可以实例化线程
对象),然后调用start()
来启动线程
编辑:ExecutorService
拥有自己的队列,因此这可能会造成混乱。。这里有一些东西可以让你开始
public class Main {
public static void main(String[] args) {
//The numbers are just silly tune parameters. Refer to the API.
//The important thing is, we are passing a bounded queue.
ExecutorService consumer = new ThreadPoolExecutor(1,4,30,TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>(100));
//No need to bound the queue for this executor.
//Use utility method instead of the complicated Constructor.
ExecutorService producer = Executors.newSingleThreadExecutor();
Runnable produce = new Produce(consumer);
producer.submit(produce);
}
}
class Produce implements Runnable {
private final ExecutorService consumer;
public Produce(ExecutorService consumer) {
this.consumer = consumer;
}
@Override
public void run() {
Pancake cake = Pan.cook();
Runnable consume = new Consume(cake);
consumer.submit(consume);
}
}
class Consume implements Runnable {
private final Pancake cake;
public Consume(Pancake cake){
this.cake = cake;
}
@Override
public void run() {
cake.eat();
}
}
这样,您可以通过调用.shutdownNow()
关闭执行器。如果您使用while(true)
,它将不会关闭
还请注意,生产者
仍然容易受到运行时异常
(即一个运行时异常
将停止处理)
Java代码“BlockingQueue”,它具有同步的put和get方法李>
Java代码“Producer”,生成数据的Producer线程
Java代码“Consumer”,用于消费线程生成的数据
Java代码“ProducerConsumer_Main”,用于启动生产者和消费者线程的主函数
BlockingQueue.java
public class BlockingQueue
{
int item;
boolean available = false;
public synchronized void put(int value)
{
while (available == true)
{
try
{
wait();
} catch (InterruptedException e) {
}
}
item = value;
available = true;
notifyAll();
}
public synchronized int get()
{
while(available == false)
{
try
{
wait();
}
catch(InterruptedException e){
}
}
available = false;
notifyAll();
return item;
}
}
package com.sukanya.producer_Consumer;
public class Consumer extends Thread
{
blockingQueue queue;
private int number;
Consumer(BlockingQueue queue,int number)
{
this.queue = queue;
this.number = number;
}
public void run()
{
int value = 0;
for (int i = 0; i < 10; i++)
{
value = queue.get();
System.out.println("Consumer #" + this.number+ " got: " + value);
}
}
}
Consumer.java
public class BlockingQueue
{
int item;
boolean available = false;
public synchronized void put(int value)
{
while (available == true)
{
try
{
wait();
} catch (InterruptedException e) {
}
}
item = value;
available = true;
notifyAll();
}
public synchronized int get()
{
while(available == false)
{
try
{
wait();
}
catch(InterruptedException e){
}
}
available = false;
notifyAll();
return item;
}
}
package com.sukanya.producer_Consumer;
public class Consumer extends Thread
{
blockingQueue queue;
private int number;
Consumer(BlockingQueue queue,int number)
{
this.queue = queue;
this.number = number;
}
public void run()
{
int value = 0;
for (int i = 0; i < 10; i++)
{
value = queue.get();
System.out.println("Consumer #" + this.number+ " got: " + value);
}
}
}
我已经将cletus提出的答案扩展到工作代码示例
一个ExecutorService
(pes)接受Producer
任务
一个ExecutorService
(ces)接受消费者
任务
生产者
和消费者
共享封锁队列
多个Producer
任务生成不同的数字
任何消费者
任务都可以使用生产者
代码:
注意。如果您不需要多个生产者和消费者,请保留单个生产者和消费者。我添加了多个生产者和消费者,以展示在多个生产者和消费者之间阻止队列的功能。这是一段非常简单的代码
import java.util.*;
// @author : rootTraveller, June 2017
class ProducerConsumer {
public static void main(String[] args) throws Exception {
Queue<Integer> queue = new LinkedList<>();
Integer buffer = new Integer(10); //Important buffer or queue size, change as per need.
Producer producerThread = new Producer(queue, buffer, "PRODUCER");
Consumer consumerThread = new Consumer(queue, buffer, "CONSUMER");
producerThread.start();
consumerThread.start();
}
}
class Producer extends Thread {
private Queue<Integer> queue;
private int queueSize ;
public Producer (Queue<Integer> queueIn, int queueSizeIn, String ThreadName){
super(ThreadName);
this.queue = queueIn;
this.queueSize = queueSizeIn;
}
public void run() {
while(true){
synchronized (queue) {
while(queue.size() == queueSize){
System.out.println(Thread.currentThread().getName() + " FULL : waiting...\n");
try{
queue.wait(); //Important
} catch (Exception ex) {
ex.printStackTrace();
}
}
//queue empty then produce one, add and notify
int randomInt = new Random().nextInt();
System.out.println(Thread.currentThread().getName() + " producing... : " + randomInt);
queue.add(randomInt);
queue.notifyAll(); //Important
} //synchronized ends here : NOTE
}
}
}
class Consumer extends Thread {
private Queue<Integer> queue;
private int queueSize;
public Consumer(Queue<Integer> queueIn, int queueSizeIn, String ThreadName){
super (ThreadName);
this.queue = queueIn;
this.queueSize = queueSizeIn;
}
public void run() {
while(true){
synchronized (queue) {
while(queue.isEmpty()){
System.out.println(Thread.currentThread().getName() + " Empty : waiting...\n");
try {
queue.wait(); //Important
} catch (Exception ex) {
ex.printStackTrace();
}
}
//queue not empty then consume one and notify
System.out.println(Thread.currentThread().getName() + " consuming... : " + queue.remove());
queue.notifyAll();
} //synchronized ends here : NOTE
}
}
}
import java.util.*;
//@author:roottraveler,