Welcome to MLink Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
142 views
in Technique[技术] by (71.8m points)

java - Wait and Notify problem with many threads

I am having a problem with the methods wait() and notify(). I have three threads, one is called Management (which is responsible for managing the others threads) and two called Worker, both classes implement Runnable. The Management submit one task for each Worker and keep working. The Worker, when recieve a task needs to process the task and wait for other task.

In my Management, I have a method called doWork, that basically send the tasks to the Workers and notify them. All implementation is described below:

WorkerManagement (please, consider constructor and others methods implemented):

public class WorkerManagement extends ActiveObject{
    private volatile Map<Worker, Boolean> workers = new HashMap<>();
    @Override
    protected void doWork() {
        while(!mustStop()){
            if(getAvailableThreadsSize() != workers.size()){
                continue;
            }
            WorkQueue highestPriorityWorkQueue = workQueues.getHighestPriorityWorkQueue();
            if(highestPriorityWorkQueue == null){
                continue;
            }
            tasks = highestPriorityWorkQueue.pollList();
            for (Map.Entry<Worker, Boolean> entry : workers.entrySet()) {
                Worker worker = entry.getKey();
                worker.updateTask(tasks.poll());
                workers.replace(worker, Boolean.FALSE);
                synchronized (worker) {
                    worker.notify();
                }
            }
        }
    }
    private int getAvailableThreadsSize(){
        int availables = 0;
        for (Map.Entry<Worker, Boolean> entry : workers.entrySet()) {
            Boolean available = entry.getValue();
            if(available){
                availables++;
            }
        }
        return availables;
    }
}

Worker (please, consider constructor and others methods implemented):

public class Worker extends ActiveObject{
    private WorkerManagement workerManagement;
    private Task task;

    @Override
    protected void doWork() {
        while (!mustStop()) {
            System.out.println(Thread.currentThread().getName()+" is Alive:"+Thread.currentThread().isAlive());
            try {
                task.execute();

                workerManagement.setAvailable(this);

                synchronized(this){
                    System.out.println(Thread.currentThread().getName()+" is Alive:"+Thread.currentThread().isAlive());
                    wait();
                }
            } catch (Exception ex) {
                LOGGER.log(Level.SEVERE, "Exception in Worker: " + getName(), ex);
            }
            
        }
    }

}

PS: ActiveObject is an inner class that implements Runnable.

@EDIT: My problem, basically is: One worker is always waiting and the other is always alive. So, when I debug the code on WorkerManagement the method getAvailableThreadsSize is always returning 1 and the workers.size() is returning 2. An example of output of my doWork print's is:

WorkerThread-1 is Alive:true
WorkerThread-2 is Alive:true
WorkerThread-2 is Alive:true
WorkerThread-2 is Alive:true
WorkerThread-2 is Alive:true

Which means that the WorkerThread-2 is always working while WorkerThread-1 is waiting (except the first execution).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Whit this code

if (getAvailableThreadsSize() != workers.size()){
    continue;
}

if these is a thread running the number of available threads will be workers.size()-1 so only one thread can be activate

try to change to

if (getAvailableThreadsSize() >0){
    continue;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to MLink Developer Q&A Community for programmer and developer-Open, Learning and Share

1.2m questions

2.1m answers

5 comments

56.5k users

...