K
K
Kirill Zhilyaev2019-10-16 21:43:01
Java
Kirill Zhilyaev, 2019-10-16 21:43:01

How to put a thread to sleep before a signal from another thread?

There are 2 streams. They take one Runnable from the common array and execute it and remove it from the array. From other flows these same Runnable are interposed. But when using wait and notify or ReentrantLock.Condition await/signal I have IllegalMonitorStateException

package ru.irina.mongo;

import com.mongodb.DB;
import com.mongodb.MongoClient;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;

import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class MongoWorkers {

    private final static ArrayList<Runnable> tasks = new ArrayList<>();
    private final static ArrayList<DB> mongoDatabases = new ArrayList<>();
    private final static ArrayList<Worker> workers = new ArrayList<>();

    private static final Condition condition = new ReentrantLock().newCondition();

    public static void putTask(Runnable task) {
        synchronized (tasks) {
            tasks.add(task);
        }

        condition.signalAll();
    }

    public static void runWorkers(int threadCount) {

        if (!mongoDatabases.isEmpty())
            throw new IllegalStateException("Workers уже started");

        for (int i = 0; i < threadCount; ++i) {
            Worker worker = new Worker();
            worker.start();
            workers.add(worker);
        }

        System.out.println("[Worker] started " + threadCount + " threads");
    }

    public static DB getDB() {

        System.out.println("[Worker] request DB");

        synchronized (mongoDatabases) {
            if (!mongoDatabases.isEmpty()) {
                DB db = mongoDatabases.get(0);
                mongoDatabases.remove(0);
                return db;
            }

            return null;
        }
    }

    public static void returnDB(DB db) {

        System.out.println("[Worker] return DB");

        synchronized (mongoDatabases) {
            mongoDatabases.add(db);
        }
    }

    static class Worker extends Thread {
        Worker() {

            synchronized (mongoDatabases) {
                mongoDatabases.add(db);
            }

            setDaemon(true);
        }

        @Override
        public void run() {
            while (isAlive()) {
                Runnable runnable = null;

                synchronized (tasks) {
                    if (!tasks.isEmpty()) {
                        runnable = tasks.get(0);
                        tasks.remove(0);
                    }
                }

                if (runnable != null)
                    runnable.run();
                else {
                    try {
                        condition.await();
                    } catch (InterruptedException e) {
                        // ...
                    }
                }

            }

        }
    }

}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
S
Sergey Gornostaev, 2019-10-17
@kirill_782

awaitand notifycan only be called on the captured monitor.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question