Welcome to the Java Programming Forums


The professional, friendly Java community. 21,500 members and growing!


The Java Programming Forums are a community of Java programmers from all around the World. Our members have a wide range of skills and they all have one thing in common: A passion to learn and code Java. We invite beginner Java programmers right through to Java professionals to post here and share your knowledge. Become a part of the community, help others, expand your knowledge of Java and enjoy talking with like minded people. Registration is quick and best of all free. We look forward to meeting you.


>> REGISTER NOW TO START POSTING


Members have full access to the forums. Advertisements are removed for registered users.

Results 1 to 6 of 6

Thread: How to notify() and proceed past wait()

  1. #1
    Junior Member
    Join Date
    Feb 2012
    Posts
    3
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Cool How to notify() and proceed past wait()

    So I'm writing a JUnit test suite for a Runnable object, but for some reason the thread hangs at wait() within run() after a notify() is invoked by test.

    Here's the code for the test Suite:

    package test;
     
    import java.awt.event.ActionListener;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.Executor;
    import java.util.concurrent.FutureTask;
    import java.util.concurrent.ScheduledThreadPoolExecutor;
     
    import org.junit.Test;
    import static org.junit.Assert.*;
    import org.junit.Before;
    import java.io.IOException;
    import junit.framework.*;
    import atm.ATM;
    import simulation.Simulation;
    import banking.Money;
    import simulation.GUI;
    import simulation.SimEnvelopeAcceptor;
     
    public class ATMTest {
     
    	@SuppressWarnings("unchecked")
    	public static <T, R> R invokeMethod(T object, String method, Object... args) {
    		//Extract class information from objects
    		Class<?>[] argTypes = new Class<?>[args.length];
    		for(int i = 0; i < args.length; i++) {
    			argTypes[i] = args[i].getClass();
    		}
     
    		try {
    			Method m = object.getClass().getDeclaredMethod(method, argTypes);
    			m.setAccessible(true);
    			return (R) m.invoke(object, args);
    		} catch (Exception e) {
    			fail(e.getMessage());
    		}
    		return null;
    	}
     
    	@SuppressWarnings("unchecked")
    	public static <T,R> R getField(T object, String field) {
    		try {
    			Field f = object.getClass().getDeclaredField(field);
    			f.setAccessible(true);
    			return (R) f.get(object);
    		} catch (Exception e) {
    			fail(e.getMessage());
    		}
    		return null;
    	}
     
    	public static <T,R> void setField(T object, String field, R value) {
    		try {
    			Field f = object.getClass().getDeclaredField(field);
    			f.setAccessible(true);
    			f.set(object, value);
    		} catch (Exception e) {
    			fail(e.getMessage());
    		}
    	}
     
    	@Test
    	public void ConstructorTest(){
    		 ATM atm = new ATM(42, "Gordon College", "First National Bank of Podunk", null);
    		 assertEquals(42, getField(atm, "id"));
    		 assertEquals("Gordon College", getField(atm, "place"));
    		 assertEquals("First National Bank of Podunk", getField(atm, "bankName"));
    		 assertEquals(null, getField(atm, "bankAddress"));
    		 assertNotNull(getField(atm, "log"));
    		 assertNotNull(getField(atm, "cardReader"));
    		 assertNotNull(getField(atm, "cashDispenser"));
    		 assertNotNull(getField(atm, "customerConsole"));
    		 assertNotNull(getField(atm, "envelopeAcceptor"));
    		 assertNotNull(getField(atm, "networkToBank"));
    		 assertNotNull(getField(atm, "operatorPanel"));
    		 assertNotNull(getField(atm, "receiptPrinter"));
    		 assertEquals(0, getField(atm, "state"));
    		 assertEquals(false, getField(atm, "switchOn"));
    		 assertEquals(false, getField(atm, "cardInserted"));
     
    	  }
     
    	ATM atm = new ATM(42, "Gordon College", "First National Bank of Podunk", null);
    	Simulation sim = new Simulation(atm);
     
    	@Test
    	public void runPathsTest() throws Exception {
    		Executor executor = new ScheduledThreadPoolExecutor(1);
    		try {
    			executor.execute(atm);
    			Thread.sleep(2000);
    		} catch (InterruptedException e) {
    			fail(e.getMessage());
    		}
    	    atm.switchOn();
    	    Thread.sleep(5000);
    	    atm.cardInserted();
     
     
    	}
     
     
    	@Test
    	public void getIDTest(){
    		 assertEquals(42, getField(atm, "id"));
    	}
    	@Test
    	public void getPlaceTest(){
    		assertEquals("Gordon College", getField(atm, "place"));
    	}
    	@Test
    	public void getBankNameTest(){
    		assertEquals("First National Bank of Podunk", getField(atm, "bankName"));		
    	}
    	@Test
    	public void getBankAddressTest(){
    		assertEquals(null, getField(atm, "bankAddress"));		
    	}
    	@Test
    	public void getCardReadTest(){
    		assertNotNull(getField(atm, "cardReader"));
    	}
    	@Test
    	public void getCashDispenserTest(){
    			assertNotNull(getField(atm, "cashDispenser"));
    	}
    	@Test
    	public void getCustomerConsoleTest(){
    			assertNotNull(getField(atm, "customerConsole"));
    	}
    	@Test
    	public void getEnvelopeAccepterTest(){
    		assertNotNull(getField(atm, "envelopeAcceptor"));
    	}
    	@Test
    	public void getLogTest(){
    		assertNotNull(getField(atm, "log"));
    	}
    	@Test
    	public void getNetworkToBankTest(){
    		assertNotNull(getField(atm, "networkToBank"));
    	}
    	@Test
    	public void getOperatorPanelTest(){
    		assertNotNull(getField(atm, "operatorPanel"));
    	}
    	@Test
    	public void getReceiptPrinterTest(){
    		assertNotNull(getField(atm, "receiptPrinter"));
    	}
    	@Test
    	public void switchOnTest(){
    		atm.switchOn();
    		assertEquals(true, getField(atm, "switchOn"));
    	}
    	@Test
    	public void switchOffTest(){
    		atm.switchOff();
    		assertEquals(false, getField(atm, "switchOn"));
    	}
    	@Test
    	public void cardInsertedTest(){
    		atm.cardInserted();
    		assertEquals(true, getField(atm, "cardInserted"));
    	}
     
    	/*@Test
    	public void methodSequenceProtocolTest(){
    		ATM theATM = null;
    		try{
    			theATM.getID();
    		} catch(Exception e){
    		  	System.out.println("You must create an ATM ")
    		}
    	}*/
     
    }

    And here's the code for the Runnable ATM Class that is being tested. My emma code-coverage report indicates that the run method never executes past the first wait(), so apparently wait() never receives a message from notify(), eventhough a switchOn() and cardInserted() are invoked (from the test case) which each contain invocations of notify().

    /*
     * ATM Example system - file ATM.java
     *
     * copyright (c) 2001 - Russell C. Bjork
     *
     */
     
    package atm;
    import java.net.InetAddress;
    import atm.physical.*;
    import banking.Card;
    import banking.Money;
     
    /** Representation for the ATM itself.  An object of this class "owns"
     *  the objects representing the component parts of the ATM, and the
     *  communications network, and is responsible for creating customer 
     *  sessions which then use it to gain access to the component parts.
     *  This is an active class - when an instance of the class is created,
     *  a thread is executed that actually runs the system.
     */
     
    public class ATM implements Runnable
    {
        /** Constructor
         *
         *  @param id the unique ID for this ATM
         *  @param place the physical location of this ATM
         *  @param bankName the name of the bank owning this ATM
         *  @param bankAddress the Internet address of the bank
         */
        public ATM(int id, String place, String bankName, InetAddress bankAddress)
        {
            this.id = id;
            this.place = place;
            this.bankName = bankName;
            this.bankAddress = bankAddress;
     
            // Create objects corresponding to component parts
     
            log = new Log();
            cardReader = new CardReader(this);
            cashDispenser = new CashDispenser(log);
            customerConsole = new CustomerConsole();
            envelopeAcceptor = new EnvelopeAcceptor(log);
            networkToBank = new NetworkToBank(log, bankAddress);
            operatorPanel = new OperatorPanel(this);
            receiptPrinter = new ReceiptPrinter();  
     
            // Set up initial conditions when ATM first created
     
            state = OFF_STATE;
            switchOn = false;
            cardInserted = false;       
        }
     
        // Methods corresponding to major responsibilities of the ATM
     
        /** The main program/applet will create a Thread that executes
         *  this code.
         */
        public void run()
        {
            Session currentSession = null;
     
            while (true)
            {
                switch(state)
                {
                    case OFF_STATE:
     
                        customerConsole.display("Not currently available");
     
                        synchronized(this)
                        {
                            try
                            { 
                                wait();
                            }
                            catch(InterruptedException e)
                            { }
                        }
     
                        if (switchOn)
                        {
                            performStartup();
                            state = IDLE_STATE;
                        }
     
                        break;
     
                    case IDLE_STATE:
     
                        customerConsole.display("Please insert your card");
                        cardInserted = false;
     
                        synchronized(this)
                        {
                            try
                            { 
                                wait();
                            }
                            catch(InterruptedException e)
                            { }
                        }       
     
                        if (cardInserted)
                        {
                            currentSession = new Session(this);
                            state = SERVING_CUSTOMER_STATE;
                        }
                        else if (! switchOn)
                        {
                            performShutdown();
                            state = OFF_STATE;
                        }
     
                        break;
     
                    case SERVING_CUSTOMER_STATE:
     
                        // The following will not return until the session has
                        // completed
     
                        currentSession.performSession();
     
                        state = IDLE_STATE;
     
                        break;
     
                }
            }
        }
     
        /** Inform the ATM that the switch on the operator console has been moved
         *  to the "on" position.
         */
        public synchronized void switchOn()
        {
            switchOn = true;
            notify();
        }
     
        /** Inform the ATM that the switch on the operator console has been moved
         *  to the "off" position.
         */
        public synchronized void switchOff()
        {
            switchOn = false;
            notify();
        }
     
        /** Inform the ATM that a card has been inserted into the card reader.
         */
        public synchronized void cardInserted()
        {
            cardInserted = true;
            notify();
        }
     
        // The following methods allow objects of other classes to access component
        // parts of the ATM
     
        /** Accessor for id
         *
         *  @return unique id of this ATM
         */
        public int getID()
        {
            return id;
        }
     
        /** Accessor for place
         *
         *  @return physical location of this ATM
         */
        public String getPlace()
        {
            return place;
        }
     
        /** Accessor for bank name
         *
         *  @return name of bank owning this ATM
         */
        public String getBankName()
        {
            return bankName;
        }
     
        /** Accessor for card reader
         *
         *  @return card reader component of this ATM
         */
        public CardReader getCardReader()
        {
            return cardReader;
        }
     
        /** Accessor for cash dispenser
         *
         *  @return cash dispenser component of this ATM
         */
        public CashDispenser getCashDispenser()
        {
            return cashDispenser;
        }
     
        /** Accessor for customer console 
         *
         *  @return customer console component of this ATM
         */
        public CustomerConsole getCustomerConsole()
        {
            return customerConsole;
        }
     
        /** Accessor for envelope acceptor
         *
         *  @return envelope acceptor component of this ATM
         */
        public EnvelopeAcceptor getEnvelopeAcceptor()
        {
            return envelopeAcceptor;
        }
     
        /** Accessor for log
         *
         *  @return log component of this ATM
         */
        public Log getLog()
        {
            return log;
        }
     
        /** Accessor for network to bank
         *
         *  @return network connection to bank of this ATM
         */
        public NetworkToBank getNetworkToBank()
        {
            return networkToBank;
        }
     
        /** Accessor for operator panel
         *
         *  @return operator panel component of this ATM
         */
        public OperatorPanel getOperatorPanel()
        {
            return operatorPanel;
        }
     
        /** Accessor for receipt printer
         *
         *  @return receipt printer component of this ATM
         */
        public ReceiptPrinter getReceiptPrinter()
        {
            return receiptPrinter;
        }
     
        // Private methods
     
        /** Perform the System Startup use case when switch is turned on
         */
        private void performStartup()
        {
            Money initialCash = operatorPanel.getInitialCash();
            cashDispenser.setInitialCash(initialCash);
            networkToBank.openConnection();     
        }
     
        /** Perform the System Shutdown use case when switch is turned off
         */
        private void performShutdown()
        {
            networkToBank.closeConnection();
        }
     
     
        // Instance variables recording information about the ATM
     
     
        /** Unique ID for this ATM
         */
        private int id;
     
        /** Physical location of this ATM
         */
        private String place;
     
        /** Name of the bank owning this ATM
         */
        private String bankName;
     
        /** Internet address of the bank
         */
        private InetAddress bankAddress;
     
     
        // Instance variables referring to the omponent parts of the ATM
     
        /** The ATM's card reader
         */
        private CardReader cardReader;
     
        /** The ATM's cash dispenser
         */
        private CashDispenser cashDispenser;
     
        /** The ATM's customer console
         */
        private CustomerConsole customerConsole;
     
        /** The ATM's envelope acceptor
         */
        private EnvelopeAcceptor envelopeAcceptor;
     
        /** The ATM's log
         */
        private Log log;
     
        /** The ATM's network connection to the bank
         */
        private NetworkToBank networkToBank;
     
        /** The ATM's operator panel
         */
        private OperatorPanel operatorPanel;
     
        /** The ATM's receipt printer
         */
        private ReceiptPrinter receiptPrinter;
     
     
        // State information
     
     
        /** The current state of the ATM - one of the possible values listed below
         */
        private int state;
     
        /** Becomes true when the operator panel informs the ATM that the switch has
         *  been turned on - becomes false when the operator panel informs the ATM
         *  that the switch has been turned off.
         */
        private boolean switchOn;
     
        /** Becomes true when the card reader informs the ATM that a card has been
         *  inserted - the ATM will make this false when it has tried to read the
         *  card
         */
        private boolean cardInserted; 
     
     
        // Possible values for state
     
     
        /** The ATM is off.  The switch must be turned on before it can operate
         */
        private static final int OFF_STATE = 0;
     
        /** The ATM is on, but idle.  It can service a customer, or it can be shut down
         */
        private static final int IDLE_STATE = 1;
     
        /** The ATM is servicing a customer.
         */
        private static final int SERVING_CUSTOMER_STATE = 2;
    }


    What am I missing here? I'm not totally clear on concurrency, so your insight is much appreciated..

    Thanks,
    KK


  2. #2
    Super Moderator Norm's Avatar
    Join Date
    May 2010
    Location
    SW Missouri
    Posts
    20,090
    Thanks
    48
    Thanked 2,150 Times in 2,123 Posts

    Default Re: How to notify() and proceed past wait()

    For debugging add some printlns to show where the code is executing and when.
    The more places you put them the more info you will get about how you code is executing.


    If you want any help with debugging the code you will have to make an executable program with a main method that will compile, execute and show the problem.

  3. #3
    Junior Member
    Join Date
    Feb 2012
    Posts
    3
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default Re: How to notify() and proceed past wait()

    I know from the Emma code coverage report that the code in run() executes up until the first wait(), then it hangs. I'm not sure why the invocation of switchOn() in the runPathsTest() fails to notify wait(). That is my question.

  4. #4
    Super Moderator Norm's Avatar
    Join Date
    May 2010
    Location
    SW Missouri
    Posts
    20,090
    Thanks
    48
    Thanked 2,150 Times in 2,123 Posts

    Default Re: How to notify() and proceed past wait()

    That method is synchronized. Did the debugging println you should put inside of the method print?


    If you want any help with debugging the code you will have to make an executable program with a main method that will compile, execute and show the problem.

  5. #5
    Junior Member
    Join Date
    Feb 2012
    Posts
    3
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default Re: How to notify() and proceed past wait()

    Yes, I know it's synchronized, thanks. Yes, the println printed from within the condition immediately following the wait(), but the coverage report indicates that neither of the branches for if(switchOn) were taken, so the println is misleading, I think. I wrote a driver (main) with essentially the same code as the test case, and it did not throw any exceptions. If you can't read the code I provided an understand what's wrong, then I don't think writing a main will help. Do you understand why the wait() is not being notified? I think it has something to do with how notify() signals immediately....maybe nothing is waiting for it. So I probably have invoke Thread.sleep, but not sure how long and where.

  6. #6
    Super Moderator Norm's Avatar
    Join Date
    May 2010
    Location
    SW Missouri
    Posts
    20,090
    Thanks
    48
    Thanked 2,150 Times in 2,123 Posts

    Default Re: How to notify() and proceed past wait()

    If you can't read the code I provided an understand what's wrong, then I don't think writing a main will help
    That's presumptuous of you to think anyone is able to plan computer with your code and come up with the right results.
    A running program is needed for testing. If you aren't interested in getting help, that's up to you.

    it did not throw any exceptions
    You didn't say you were getting exceptions.

Similar Threads

  1. [SOLVED] Stuck and can't get past it!
    By Wonderlandslost in forum What's Wrong With My Code?
    Replies: 64
    Last Post: February 13th, 2012, 10:27 PM
  2. let first thread through, the rest has to wait
    By hamsterofdeath in forum Threads
    Replies: 0
    Last Post: November 19th, 2010, 12:32 PM
  3. How to use and notify
    By Saeid in forum Threads
    Replies: 4
    Last Post: August 12th, 2010, 11:12 AM
  4. Having Issues Past this
    By baGoGoodies111 in forum What's Wrong With My Code?
    Replies: 1
    Last Post: November 12th, 2009, 07:19 PM
  5. Delay/Wait/Pause in Java + AirBrushing
    By obliza in forum What's Wrong With My Code?
    Replies: 6
    Last Post: October 27th, 2009, 10:27 AM