3

メインスレッドの適合性によって既存の染色体を並べ替えるときに、ロボットのテストと進化を委任できるスレッドを作成しようとしています。以下は、最初のフィットネス方法です。ここでやりたいのは、テストの長さが30〜40秒なので、robotHandlerで各ゲノムをテストすることです。常にこれらのスレッドの1つだけを実行します。

現在、initialFitnessメソッドのwait()セクションに引っかかっているようです。これはマルチスレッド化の私の最初の試みなので、問題をデバッグする方法や、誰かが素晴らしい問題を見つけることができるかどうかについての助けがあります

RobotInterfaceクラスは現時点では単なるテストクラスです。log4jとsleepの宣言をコメントアウトして、これらを除外しようとしました(ちなみに、log4jはスレッドに何も記録していませんでした)。

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;

RobotInterfaceクラス

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();
}

}

CandidateTestクラス

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;
}

}

4

3 に答える 3

1

スレッドが開始された場所は見たことがありません。試す:

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

したがって、notifyAll()が呼び出されることはありません

于 2013-03-13T15:34:27.073 に答える
1

まず、robotHandlerスレッドを開始していません。したがって、メインスレッドが到達しwait()、それを通知するために他のスレッドが来ることはありません。

次に、wait()クラスinitialFitnessが属するものは何でも呼び出しますが、を呼び出しnotifyAll()ますRobotInterface。したがってRobotInterface、それを待っているすべての人(誰も)に通知し、メインコードは引き続き待機します。notifyAll()を呼び出したのと同じオブジェクトを呼び出す必要がありますwait()

私は提案します

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

   candidateTest.notify();
于 2013-03-13T15:37:00.303 に答える
0

Nathanialは頭に釘付けになりましたが、Javaで並行性を使い始めたばかりの場合は、java.util.concurrentパッケージを使用することをお勧めします。DZoneに関する優れた初心者向け記事を見つけました:http://java.dzone.com/articles/lazy-developers-introduction

于 2013-03-13T15:42:38.433 に答える