Skip to Main Content

New to Java

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Simple Concurrency (Stock Exchange)

843789Jan 23 2010 — edited Jan 23 2010
Hello all,

I'm emulating an extremely simplified stock exchange. I've got three classes; HitStock, Broker and EngageBroker (sort of a test class). HitStock must be a singleton holding stocks brokers want to buy. I should be able to use multiple Broker classes running concurrently, buying and selling the stocks from HitStock. I should print every transaction to the output. Also, HitStock stocks cannot go below 0 but can go above their initial value.

I'm not entirely satisfied with my solution. I'm looking for some improvements. Any advice will be appreciated.
/**
 * This singleton class holds HitStock stocks.
 */
public final class HitStock {

    private static final HitStock INSTANCE = new HitStock();
    private int availableStocks = 1000;

    /**
     * Instantiation disabled.
     */
    private HitStock() {
    }

    /**
     * Returns the instance of this class.
     * 
     * @return HitStock instance of this class.
     */
    public static HitStock getInstance() {
	return INSTANCE;
    }

    /**
     * Sells stocks of this class to the requesting broker.
     * 
     * @param amount
     *                Integer amount of stocks to sell.
     * @return Returns true if the transaction is performed, false otherwise.
     */
    public synchronized boolean replyToBuyRequest(final int amount) {
	if (amount < 1 || amount > availableStocks) {
	    return false;
	}
	availableStocks -= amount;
	return true;
    }

    /**
     * Buys stocks of this class from the requesting broker.
     * 
     * @param amount
     *                Integer amount of stocks to buy.
     * @return Returns true if the transaction is performed, false otherwise.
     */
    public synchronized boolean replyToSellRequest(final int amount) {
	if (amount < 1) {
	    return false;
	}
	availableStocks += amount;
	return true;
    }

    /**
     * Returns available stocks of this class.
     * 
     * @return Returns available stocks of this class.
     */
    public synchronized int getAvailableStocks() {
	return availableStocks;
    }

    /**
     * Returns a String representation of this class.
     * 
     * @return Returns a String representation of this class.
     */
    public synchronized String toString() {
	return String.format("HitStock stocks available: %d", availableStocks);
    }
}
/**
 * Class representing a stock broker, trading with HitStock stocks.
 */
public class Broker {

    private final HitStock stocks;
    private final int brokerID;
    private static int allBrokers;
    private int currentStocks;

    /**
     * Constructs a new Broker with HitStock stocks available for trading.
     * 
     * @param stocksOwned
     *                Number of available HitStock stocks.
     */
    public Broker(final int stocksOwned) {
	stocks = HitStock.getInstance();
	currentStocks = stocksOwned;
	brokerID = ++allBrokers;
    }

    /**
     * Tries to buy stocks from HitStock.
     * 
     * @param amount
     *                Number of stocks trying to buy.
     * @return Returns true if the transaction is performed, false otherwise.
     */
    public boolean requestBuy(final int amount) {
	if (amount < 1 || !stocks.replyToBuyRequest(amount)) {
	    return false;
	}
	currentStocks += amount;
	return true;
    }

    /**
     * Tries to sell stocks to HitStock.
     * 
     * @param amount
     *                Number of stocks trying to sell.
     * @return Returns true if the transaction is performed, false otherwise.
     */
    public boolean requestSell(final int amount) {
	if (amount < 1 || amount > currentStocks
		|| !stocks.replyToSellRequest(amount)) {
	    return false;
	}
	currentStocks -= amount;
	return true;
    }

    /**
     * Returns available stocks of this class.
     * 
     * @return Returns available stocks of this class.
     */
    public int getCurrentStocks() {
	return currentStocks;
    }

    /**
     * Returns the number ID of this class.
     * 
     * @return Returns the number ID of this class.
     */
    public int getBrokerId() {
	return brokerID;
    }

    /**
     * Prints the available stocks from this class and HitStock class to the
     * standard output.
     */
    public void printBrokerInfo() {
	System.out.println(this);
	System.out.format("HitStock stocks available: %d%n", stocks
		.getAvailableStocks());
    }

    /**
     * Returns a String representation of this class.
     * 
     * @return Returns a String representation of this class.
     */
    public String toString() {
	return String.format("Broker %d : %d stocks available.", brokerID,
		currentStocks);
    }
}
import java.util.Random;

/**
 * This class emulates a trading broker.
 */
public class EngageBroker implements Runnable {

    private static final Random RAND = new Random();
    private Broker broker;

    /**
     * Constructs a new EngageBroker.
     */
    public EngageBroker() {
	broker = new Broker(RAND.nextInt(250));
    }

    /**
     * Tries to buy stocks from HitStock.
     */
    private void buy() {
	broker.printBrokerInfo();
	final int amount = RAND.nextInt(500) + 1;
	final boolean success = broker.requestBuy(amount);
	if (success) {
	    System.out.format("Bought %d stocks.%n", amount);
	} else {
	    System.out.format("Failed to buy %d stocks.%n", amount);
	}
	broker.printBrokerInfo();
	System.out.println("********************");
    }

    /**
     * Tries to sell stocks from HitStock.
     */
    private void sell() {
	broker.printBrokerInfo();
	final int amount = RAND.nextInt(500) + 1;
	final boolean success = broker.requestSell(amount);
	if (success) {
	    System.out.format("Sold %d stocks.%n", amount);
	} else {
	    System.out.format("Failed to sell %d stocks.%n", amount);
	}
	broker.printBrokerInfo();
	System.out.println("********************");
    }

    /**
     * Sleeps for a random amount of time.
     * 
     * @throw InterruptedException if the thread is interrupted.
     */
    private void sleep() {
	try {
	    Thread.sleep(RAND.nextInt(2000));
	} catch (InterruptedException e) {
	}
    }

    /**
     * Emulation of the trading broker.
     */
    public void run() {
	for (int i = 0; i < 5; i++) {
	    sleep();
	    buy();
	    sleep();
	    sell();
	}
    }

    public static void main(String[] args) {
	new Thread(new EngageBroker()).start();
	new Thread(new EngageBroker()).start();
	new Thread(new EngageBroker()).start();
	new Thread(new EngageBroker()).start();
	new Thread(new EngageBroker()).start();
    }
}
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Feb 20 2010
Added on Jan 23 2010
3 comments
709 views