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

org.jpos.util.ThreadPool Maven / Gradle / Ivy

/*
 * jPOS Project [http://jpos.org]
 * Copyright (C) 2000-2023 jPOS Software SRL
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see .
 */

package org.jpos.util;

import org.jpos.core.Configurable;
import org.jpos.core.Configuration;
import org.jpos.core.ConfigurationException;
import org.jpos.util.BlockingQueue.Closed;
import org.jpos.util.NameRegistrar.NotFoundException;

import java.io.PrintStream;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Implements a ThreadPool with the ability to run simple Runnable
 * tasks as well as Jobs (supervised Runnable tasks)
 * @since 1.1
 * @author [email protected]
 * @deprecated Used Executor framework
 */
public class ThreadPool extends ThreadGroup implements LogSource, Loggeable, Configurable, ThreadPoolMBean {
    private static AtomicInteger poolNumber = new AtomicInteger(0);
    private static AtomicInteger threadNumber = new AtomicInteger(0);
    private int maxPoolSize = 1;
    private int available;
    private int running = 0;
    private int active  = 0;
    private BlockingQueue pool = new BlockingQueue();
    private Logger logger;
    private String realm;
    private int jobs = 0;
    private final String namePrefix;
    public static final int DEFAULT_MAX_THREADS = 100;
    
    public interface Supervised {
        boolean expired();
    }

    private class PooledThread extends Thread {
        Object currentJob = null;

        public PooledThread() {
            super (ThreadPool.this,
                    ThreadPool.this.namePrefix + ".PooledThread-" + threadNumber.getAndIncrement());
            setDaemon(true);
        }

        public void run () {
            String name = getName();
            try {
                while (pool.ready()) {
                    Object job = pool.dequeue();
                    if (job instanceof Runnable) {
                        setName (name + "-running");
                        synchronized (ThreadPool.this) {
                            currentJob = job;
                            active++;
                        }
                        try {
                            ((Runnable) job).run();
                            setName (name + "-idle");
                        } catch (Throwable t) {
                            setName (name + "-idle-"+t.getMessage());
                        }
                        synchronized (ThreadPool.this) {
                            currentJob = null;
                            available++;
                            active--;
                        }
                    } else {
                        synchronized (ThreadPool.this) {
                            currentJob = null;
                            available++;
                        }
                    }
                }
            } catch (InterruptedException e) {
                if (logger != null) {
                    Logger.log(new LogEvent(ThreadPool.this, e.getMessage()));
                }
            } catch (Closed e) {
                if (logger != null) {
                    Logger.log(new LogEvent(ThreadPool.this, e.getMessage()));
                }
            }
        }
        public synchronized void supervise () {
            if (currentJob != null && currentJob instanceof Supervised && ((Supervised)currentJob).expired())
                this.interrupt();
        }
    }

    /**
     * @param poolSize starting pool size
     * @param maxPoolSize maximum number of threads on this pool
     */
    public ThreadPool (int poolSize, int maxPoolSize) {
        this(poolSize, maxPoolSize, "ThreadPool");
    }
    /**
     * @param name pool name
     * @param poolSize starting pool size
     * @param maxPoolSize maximum number of threads on this pool
     */
    public ThreadPool (int poolSize, int maxPoolSize, String name) {
        super(name + "-" + poolNumber.getAndIncrement());
        this.maxPoolSize = maxPoolSize > 0 ? maxPoolSize : DEFAULT_MAX_THREADS ;
        this.available = this.maxPoolSize;
        this.namePrefix = name;
        init (poolSize);
    }
    
    private void init(int poolSize){
        while (running < Math.min (poolSize > 0 ? poolSize : 1, maxPoolSize)) {
            running++;
            new PooledThread().start();
        }
    }
    /**
     * Default constructor for ThreadPool
     */
    public ThreadPool () {
        this(1, DEFAULT_MAX_THREADS);
    }
    public void close () {
        pool.close();
    }
    public synchronized void execute(Runnable action) throws Closed {        
        if (!pool.ready())
            throw new Closed();

        if (++jobs % this.maxPoolSize == 0 || pool.consumerCount() <= 0)
            supervise();

        if (running < maxPoolSize && pool.consumerDeficit() >= 0) {
            new PooledThread().start();
            running++;
        }
        available--;
        pool.enqueue (action);
    }
    public void dump (PrintStream p, String indent) {
        String inner = indent + "  ";
        p.println (indent + "");
        if (!pool.ready())
            p.println (inner  + "");
        p.println (inner  + "" + getJobCount() + "");
        p.println (inner  + "" + getPoolSize() + "");
        p.println (inner  + ""  + getMaxPoolSize() + "");
        p.println (inner  + ""  + getIdleCount() + "");
        p.println (inner  + ""  + getActiveCount() + "");
        p.println (inner  + "" + getPendingCount() + "");
        p.println (indent + "");
    }

    /**
     * @return number of jobs processed by this pool
     */
    public int getJobCount () {
        return jobs;
    }
    /**
     * @return number of running threads
     */
    public int getPoolSize () {
        return running;
    }
    /**
     * @return max number of active threads allowed
     */
    public int getMaxPoolSize () {
        return maxPoolSize;
    }
    /**
     * @return number of active threads
     */
    public int getActiveCount () {
        return active;
    }
    /**
     * @return number of idle threads
     */
    public int getIdleCount () {
        return pool.consumerCount ();
    }
    /**
     * @return number of available threads
     */
    synchronized public int getAvailableCount () {
        return available;
    }

    /**
     * @return number of Pending jobs
     */
    public int getPendingCount () {
        return pool.pending ();
    }

    public void supervise () {
        Thread[] t = new Thread[maxPoolSize];
        int cnt = enumerate (t);
        for (int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy