ОК, как отмечают другие, лучше всего использовать пакет java.util.concurrent
. Я настоятельно рекомендую "Параллелизм Java на практике". Это отличная книга, которая охватывает почти все, что вам нужно знать.
Что касается вашей конкретной реализации, как я отметил в комментариях, не запускайте Threads из Конструкторов - это может быть небезопасно.
Если оставить в стороне, вторая реализация выглядит лучше. Вы не хотите ставить очереди в статические поля. Вы, вероятно, просто теряете гибкость ни за что.
Если вы хотите продолжить свою собственную реализацию (я полагаю, для учебной цели), предоставьте, по крайней мере, метод start()
. Вы должны сконструировать объект (вы можете создать экземпляр Thread
объекта), а затем вызвать 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();
}
}
Дальнейшее редактирование:
Для продюсера вместо while(true)
вы можете сделать что-то вроде:
@Override
public void run(){
while(!Thread.currentThread().isInterrupted()){
//do stuff
}
}
Таким образом, вы можете выключить исполнителя, позвонив по номеру .shutdownNow()
. Если вы используете while(true)
, он не выключится.
Также обратите внимание, что Producer
все еще уязвим для RuntimeExceptions
(то есть один RuntimeException
остановит обработку)