IIIA-Example : Producer-Consumer

Joinpointtypes

file: ItemProducing.java

public joinpointtype ItemProducing {
}

file: ConsumerCreation.java

public joinpointtype ConsumerCreation {
	Consumer consumer;
}

Classes

file: Item.java

public class Item {
	public int value = 0;
}

file: Producer.java

import java.util.Random;

public class Producer implements Runnable exhibits ItemProducing {

	pointcut ItemProducing : execution(Item produceItem());

	private int numberOfItems = 0;
	private Random random = new Random();

	public Producer(int numberOfItems) {
		this.numberOfItems = numberOfItems;
	}

	public void run() {

		System.out.println("[producer]\tstart producing "+numberOfItems+" items");
		for(int i = 0; i < numberOfItems; i++) {
			Item it = produceItem();
			System.out.println("[producer] item "+i+" : "+it.value);
			try {
				Thread.sleep(1000);
			} catch(InterruptedException e) {
				System.err.println(e);
			}

		}
		System.out.println("[producer] stop producing");
	}

	private Item produceItem() {
		int i = random.nextInt(10);
		Item it = new Item();
		it.value = i;
		return it;
	}

}

file: Consumer.java

import java.util.Random;

public class Consumer exhibits ConsumerCreation {

	pointcut ConsumerCreation : execution(new(..)) && this(consumer);

	private Random random = new Random();
	private boolean working = false;

	private String name;

	public Consumer(String n) {
		name = n;
	}

	public String getName() {return name;}

	public void consume(Item it) {

		working = true;
		System.out.println("["+name+"] consuming "+it.value);
		Runnable r = new Runnable() {
			public void run() {
				int sleep = random.nextInt(2000) + 750;
				System.out.println("["+name+"] sleeping for "+sleep);
				try {
					Thread.sleep(sleep);
				} catch(InterruptedException e) {
					System.err.println(e);
				}
				working = false;
				System.out.println("["+name+"] ready for new Items");
			}
		};
		Thread th = new Thread(r);
		th.start();
	}

	public boolean isWorking() {return working;}

}

Aspects

file: Dispatcher.java

import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;


public aspect Dispatcher advises ItemProducing, ConsumerCreation {

	List consumer = new ArrayList();

	after(ConsumerCreation creation) returning {
		System.out.println("[dispatcher] add new consumer: "+creation.consumer.getName());
		consumer.add(creation.consumer);
	}


	after(ItemProducing producing) returning(Item it) {
		System.out.println("[dispatch] recieve item : "+it.value);
		boolean check = check(it);
		if(check) {
			dispatch(it);
		} else {
			System.out.println("[checking] invalid value "+it.value+"! item rejected");
		}
	}

	private boolean check(Item it) {
		return it.value != 0;
	}

	private void dispatch(final Item it) {
		Runnable r = new Runnable() {
			public void run() {
				System.out.println("[dispatch] search for idle consumer");

				boolean searching = true;
				int tries = 0;
				while(searching) {
					if(tries > 0) {
						System.out.println("[dispacth] no consumer idle, try again");
					}
					for(Iterator i = consumer.iterator(); i.hasNext();) {
						Consumer c = (Consumer) i.next();
						if(!c.isWorking()) {
							System.out.println("[dispatch] "+c.getName()+" is idle ...");
							c.consume(it);
							searching = false;
							break;
						}
						System.out.println("[dispatch] "+c.getName()+" is busy");
					}
					tries++;
					try {
						Thread.sleep(1000);
					} catch(InterruptedException e) {
						System.err.println(e);
					}
				}
			}
		};

		Thread th = new Thread(r);
		th.start();

	}
}

Back to main page