All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.anrisoftware.globalpom.threads.watchdog.ThreadsWatchdog Maven / Gradle / Ivy

/*
 * Copyright 2013-2025 Erwin Müller 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.anrisoftware.globalpom.threads.watchdog;

import static java.util.Collections.synchronizedList;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;

import jakarta.inject.Inject;

import org.joda.time.Duration;

import com.anrisoftware.globalpom.threads.external.core.ListenableFuture;
import com.anrisoftware.globalpom.threads.external.core.ListenableFuture.Status;
import com.anrisoftware.globalpom.threads.external.core.Threads;
import com.anrisoftware.globalpom.threads.external.listenablefuture.DefaultListenableFuture;

/**
 * Keeps track of the submitted tasks.
 *
 * @author Erwin Mueller, [email protected]
 * @since 1.5
 */
public class ThreadsWatchdog {

    private final ThreadsWatchdogLogger log;

    private List> tasks;

    private ExecutorService executor;

    private AtomicBoolean notified;

    @Inject
    ThreadsWatchdog(ThreadsWatchdogLogger logger) {
        this.log = logger;
        this.tasks = synchronizedList(new ArrayList>());
        this.notified = new AtomicBoolean(false);
    }

    /**
     * Sets the executor service to submit tasks.
     *
     * @param executor the {@link ExecutorService}.
     */
    public void setExecutor(ExecutorService executor) {
        this.executor = executor;
    }

    /**
     * @see Threads#submit(Callable, PropertyChangeListener...)
     *
     * @param callable  the {@link Callable}
     *
     * @param listeners the {@link PropertyChangeListener} listeners.
     *
     * @param        the task type.
     *
     * @return the task.
     */
    public  DefaultListenableFuture submit(Callable callable, PropertyChangeListener... listeners) {
        DefaultListenableFuture futureTask;
        futureTask = new DefaultListenableFuture(callable);
        return submit(futureTask, listeners);
    }

    /**
     * @see Threads#submit(Runnable, Object, PropertyChangeListener...)
     *
     * @param runable   the {@link Runnable}
     *
     * @param result    the result.
     *
     * @param listeners the {@link PropertyChangeListener} listeners.
     *
     * @param        the result type.
     *
     * @return the task.
     */
    public  ListenableFuture submit(Runnable runable, V result, PropertyChangeListener... listeners) {
        DefaultListenableFuture futureTask;
        futureTask = new DefaultListenableFuture(runable, result);
        return submit(futureTask, listeners);
    }

    private  DefaultListenableFuture submit(final DefaultListenableFuture task,
            PropertyChangeListener[] listeners) {
        for (PropertyChangeListener l : listeners) {
            task.addPropertyChangeListener(l);
        }
        task.addPropertyChangeListener(new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                Status status = (Status) evt.getNewValue();
                if (status == Status.DONE) {
                    tasks.remove(task);
                    log.taskDone(task);
                    unlockWait();
                }
            }

        });
        tasks.add(task);
        executor.submit(task);
        log.taskSubmitted(task);
        return task;
    }

    private void unlockWait() {
        synchronized (this) {
            notified.set(true);
            notifyAll();
        }
    }

    /**
     * @see Threads#getTasks()
     *
     * @return a copy of the submitted tasks.
     */
    public List> getTasks() {
        synchronized (tasks) {
            return new ArrayList>(tasks);
        }
    }

    /**
     * @see Threads#waitForTasks()
     *
     * @throws InterruptedException if any of the tasks was interrupted.
     */
    public void waitForTasks() throws InterruptedException {
        while (tasks.size() > 0) {
            synchronized (this) {
                wait(100);
            }
        }
    }

    /**
     * @see Threads#waitForTasks(Duration)
     *
     * @param timeout the {@link Duration} timeout duration.
     *
     * @return the {@link List} of {@link Future} futures.
     *
     * @throws InterruptedException if any of the tasks was interrupted.
     */
    public List> waitForTasks(Duration timeout) throws InterruptedException {
        while (tasks.size() > 0) {
            synchronized (this) {
                wait(timeout.getMillis());
                if (!notified.compareAndSet(true, false)) {
                    break;
                }
            }
        }
        return tasks;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy