import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import org.apache.log4j.Logger;
public class ProducerAndConsumer {
private static final Logger LOGGER = Logger
.getLogger(ProducerAndConsumer.class);
interface Task {
public void execute() throws Exception;
}
abstract class AbstractTaskImpl implements Task {
protected String name;
public AbstractTaskImpl(String name) {
super();
this.name = name;
}
@Override
public String toString() {
return "AbstractTaskImpl [name=" + name + "]";
}
@Override
public int hashCode() {
final int prime = 37;
int result = 17;
result = prime * result + getOuterType().hashCode();
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AbstractTaskImpl other = (AbstractTaskImpl) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public void execute() throws Exception {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(this + " start working.");
}
try {
if (beforeDoIt()) {
if (doIt()) {
doItSuccess();
} else {
doItFailure();
}
}
} finally {
doItFinally();
}
}
protected abstract boolean beforeDoIt() throws Exception;
protected abstract boolean doIt() throws Exception;
protected abstract void doItSuccess() throws Exception;
protected abstract void doItFailure() throws Exception;
protected abstract void doItFinally() throws Exception;
private ProducerAndConsumer getOuterType() {
return ProducerAndConsumer.this;
}
}
class TaskImpl extends AbstractTaskImpl {
public TaskImpl(String name) {
super(name);
}
@Override
protected boolean beforeDoIt() throws Exception {
LOGGER.debug("ProducerAndConsumer.TaskImpl.beforeDoIt()");
return true;
}
@Override
protected boolean doIt() throws Exception {
LOGGER.debug("ProducerAndConsumer.TaskImpl.doIt()");
return true;
}
@Override
protected void doItSuccess() throws Exception {
LOGGER.debug("ProducerAndConsumer.TaskImpl.doItSuccess()");
}
@Override
protected void doItFailure() throws Exception {
LOGGER.debug("ProducerAndConsumer.TaskImpl.doItFailure()");
}
@Override
protected void doItFinally() throws Exception {
LOGGER.debug("ProducerAndConsumer.TaskImpl.doItFinally()");
}
}
abstract class AbstractRunnable implements Runnable {
protected String name;
protected BlockingQueue<Task> queue;
public AbstractRunnable(String name, BlockingQueue<Task> queue) {
super();
this.name = name;
this.queue = queue;
}
public void run() {
Thread.currentThread().setName(name);
LOGGER.info(name + " start to work.");
executeRun();
}
public abstract void executeRun();
}
class Producer extends AbstractRunnable {
public Producer(String name, BlockingQueue<Task> queue) {
super(name, queue);
}
@Override
public void executeRun() {
while (true) {
try {
LOGGER.info("start to produce tasks.");
Collection<Task> tasks = getTasks();
for (Task t : tasks) {
queue.put(t);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(t + " was put into queue.");
}
}
long sleepTime = 5L;
LOGGER.info(name + " will sleep " + sleepTime + " seconds.");
TimeUnit.SECONDS.sleep(sleepTime);
} catch (Exception e) {
LOGGER.error("Error:" + e.getMessage(), e);
}
}
}
private Collection<Task> getTasks() {
List<Task> tasks = new ArrayList<Task>();
for (int i = 0; i < 10; i++) {
tasks.add(new TaskImpl("task-" + i));
}
return tasks;
}
}
class Consumer extends AbstractRunnable {
public Consumer(String name, BlockingQueue<Task> queue) {
super(name, queue);
}
@Override
public void executeRun() {
while (true) {
try {
consume(queue.take());
} catch (Exception e) {
LOGGER.error("Error:" + e.getMessage(), e);
}
}
}
private void consume(Task task) throws Exception {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(task + " was take from queue.");
}
task.execute();
}
}
public static void main(String[] args) {
ProducerAndConsumer instance = new ProducerAndConsumer();
BlockingQueue<ProducerAndConsumer.Task> queue = new LinkedBlockingQueue<ProducerAndConsumer.Task>();
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(instance.new Producer("producer-0", queue));
int threadPoolSize = Runtime.getRuntime().availableProcessors() * 4;
for (int i = 0; i < threadPoolSize; i++) {
exec.execute(instance.new Consumer("consumer-" + i, queue));
}
exec.shutdown();
}
}