Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stuck in wait() for thread execution to return

I'm trying to write a thread that I can delegate testing and evolution of a robot to while I sort the existing chromosomes by fitness in the main thread. Below is the initial fitness method. What I want to do here is to have each genome tested by a robotHandler as the tests are 30 - 40 seconds long. I will only be running one of these threads at any given time.

Currently I seem to get caught in the wait() section of the intialFitness method. This is my first attempt at multithreading so any help as to how to debug the problem or if someone can spot the issue that would be fantastic

The RobotInterface class is just a testing class at the moment, I have commented out the log4j and sleep declarations to try and rule these out (Incidentally log4j was not logging anything in the thread if that helps)

public synchronized ArrayList<Genome> initialFitness( ArrayList<Genome> population)
{
    for ( int i = 0; i < population.size(); i++  )
    {
        candidateTest = new CandidateTest(population.get(i));
        Thread robotHandler = new Thread(new RobotInterface( candidateTest));
        while(! (candidateTest.finishedYet() ))
        {
            try
            {
                wait();
            }
            catch (InterruptedException e)
            {
                logger.debug("The initialFitness method was interrupted, this shouldn't happen");
            }
        }
        population.set(i, candidateTest.getCandidate());
    }
    return population;
}

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import java.util.Random;

The RobotInterface Class

public class RobotInterface implements Runnable
{
// create a serial connection
// transmit a string and check for response
// wait for evaluation
// take evaluation
private CandidateTest candidate;
private Random rng = new Random();

//protected static Logger logger = Logger.getLogger("Thread" + Thread.currentThread().getName());

public RobotInterface(CandidateTest test)
{
    this.candidate = test;
    //PropertyConfigurator.configure("log4j.properties");
}

public void evaluate (Genome genome)
{
    //send to robot and return fitness
    genome.setFitness(rng.nextDouble());
    //logger.debug("fitness is " + genome.getFitness());
    try
    {
        //logger.debug("Thread sleeping for 4 seconds");
        //Thread.sleep(4000);
    }
    catch(Exception E)
    {

    }

}

public void run() 
{
    //logger.debug("entering run of Robot Interface");
    //logger.debug("Send Genome via serial and wait for a response");
    Genome testSubject = candidate.getCandidate(); 
    evaluate(testSubject);
    candidate.finished();
    notifyAll();
}

}

The CandidateTest Class

public class CandidateTest
{
private volatile Genome candidate;
private volatile boolean testFinished = false;

public CandidateTest(Genome g)
{
    candidate = g;
}

public synchronized Genome getCandidate()
{
    return candidate;
}

public synchronized void finished()
{
    testFinished = true;
}

public synchronized boolean finishedYet()
{
    return testFinished;
}

}

like image 202
LiamRyan Avatar asked Jun 29 '26 18:06

LiamRyan


2 Answers

First, you are not starting the robotHandler thread. So your main thread gets to wait() and then no other thread ever comes along to notify it.

Second, you call wait() on whatever class initialFitness belongs to, but you call notifyAll() on RobotInterface. So RobotInterface will notify everyone who is waiting on it (nobody) and your main code will continue to wait. You need to call notifyAll() on the same object on which you called wait().

I suggest

synchronized(candidateTest) {
   candidateTest.wait();
}

and

   candidateTest.notify();
like image 62
Nathaniel Waisbrot Avatar answered Jul 01 '26 08:07

Nathaniel Waisbrot


Never seen where the Thread is started. Try:

 Thread robotHandler = new Thread(new RobotInterface( candidateTest)).start();

so your notifyAll() is never called

like image 44
MemLeak Avatar answered Jul 01 '26 08:07

MemLeak



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!