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

com.pi4j.concurrent.DefaultExecutorServiceFactory Maven / Gradle / Ivy

Go to download

This bundle wraps Pi4j (http://pi4j.com) that wraps the native code Wiring Pi (http://wiringpi.com). It wraps these libraries to make them OSGi friendly and allow them to work together with the OSGi enRoute IoT circuit library (osgi.enroute.iot.circuit). The bundle will first use Pi4J to detect on what hardware it runs. If it runs on an appropriate type, it will register a component that can be configured with Metatype. The Metatype defines a full blown configuration template for all the Pi's functions. The GPIO's are registered as components for the circuit. Regardless of the success of the configuration, this bundle will also register a GpioController service, which is the main Pi4J class.

The newest version!
package com.pi4j.concurrent;

/*
 * #%L
 * **********************************************************************
 * ORGANIZATION  :  Pi4J
 * PROJECT       :  Pi4J :: Java Library (Core)
 * FILENAME      :  DefaultExecutorServiceFactory.java  
 * 
 * This file is part of the Pi4J project. More information about 
 * this project can be found here:  http://www.pi4j.com/
 * **********************************************************************
 * %%
 * Copyright (C) 2012 - 2015 Pi4J
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser 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 General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */


import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicLong;

public class DefaultExecutorServiceFactory implements ExecutorServiceFactory {

    public static int MAX_THREADS_IN_POOL = 25;
    private static List singleThreadExecutorServices = new ArrayList<>();

    // this seemingly odd pattern is the recommended way to lazy-initialize static fields in effective java.
    // The static "holder" class doesn't have it's static initializer called until it is accessed - and it's not accessed until the
    // getInternalScheduledExecutor() method is called.
    //
    // (see effective java item 71:Use lazy initialization judiciously)
    private static class ScheduledExecutorServiceHolder {
        static final ScheduledExecutorService heldExecutor = Executors.newScheduledThreadPool(MAX_THREADS_IN_POOL, getThreadFactory("pi4j-scheduled-executor-%d"));
    }
    private static ScheduledExecutorService getInternalScheduledExecutorService() {
        return ScheduledExecutorServiceHolder.heldExecutor;
    }
    private static class ScheduledExecutorServiceWrapperHolder {
        static final ScheduledExecutorServiceWrapper heldWrapper = new ScheduledExecutorServiceWrapper(getInternalScheduledExecutorService());
    }
    private static ScheduledExecutorServiceWrapper getScheduledExecutorServiceWrapper() {
        return ScheduledExecutorServiceWrapperHolder.heldWrapper;
    }

    // follow a similar lazy initialization pattern for the gpio events
    private static class GpioEventExecutorServiceHolder {
        static final ExecutorService heldExecutor = Executors.newCachedThreadPool(getThreadFactory("pi4j-gpio-event-executor-%d"));
    }
    private static ExecutorService getInternalGpioExecutorService() {
        return GpioEventExecutorServiceHolder.heldExecutor;
    }
    private static class GpioEventExecutorServiceWrapperHolder {
        static final ExecutorService heldWrapper = new ShutdownDisabledExecutorWrapper(getInternalGpioExecutorService());
    }
    private static ExecutorService getGpioEventExecutorServiceWrapper() {
        return GpioEventExecutorServiceWrapperHolder.heldWrapper;
    }

    /**
     * return an instance to the thread factory used to create new executor services
     */
    private static ThreadFactory getThreadFactory(final String nameFormat) {
        final ThreadFactory defaultThreadFactory = Executors.defaultThreadFactory();
        return new ThreadFactory() {
            final AtomicLong count = (nameFormat != null) ? new AtomicLong(0) : null;

            @Override
            public Thread newThread(Runnable runnable) {
                Thread thread = defaultThreadFactory.newThread(runnable);
                if (nameFormat != null) {
                    thread.setName(String.format(nameFormat, count.getAndIncrement()));
                }
                return thread;
            }
        };
    }

    /**
     * return an instance to the scheduled executor service (wrapper)
     */
    public ScheduledExecutorService getScheduledExecutorService() {
        // we return the protected wrapper to prevent any consumers from 
        // being able to shutdown the scheduled executor service
        return getScheduledExecutorServiceWrapper();
    }

    @Override
    public ExecutorService getGpioEventExecutorService() {
        // we return the protected wrapper to prevent any consumers from
        // being able to shutdown the scheduled executor service
        return getGpioEventExecutorServiceWrapper();
    }

    /**
     * return a new instance of a single thread executor service
     *
     * This method is deprecated in favor of the getGpioEventExecutorService - which provides better guarantees around resource
     * management
     */
    @Override
    public ExecutorService newSingleThreadExecutorService() {

        // create new single thread executor service
        ExecutorService singleThreadExecutorService = Executors.newSingleThreadExecutor(getThreadFactory("pi4j-single-executor-%d"));

        // add new instance to managed collection
        singleThreadExecutorServices.add(singleThreadExecutorService);

        // return new executor service
        return singleThreadExecutorService;
    }

    /**
     * shutdown executor threads
     */
    public void shutdown() {
        // shutdown each single thread executor in the managed collection
        for (ExecutorService singleThreadExecutorService : singleThreadExecutorServices) {
            shutdownExecutor(singleThreadExecutorService);
        }

        // shutdown scheduled executor instance
        shutdownExecutor(getInternalScheduledExecutorService());
        shutdownExecutor(getInternalGpioExecutorService());

    }

    private void shutdownExecutor(ExecutorService executor) {
        if (executor != null) {
            if (!executor.isShutdown()) {
                // this is a forceful shutdown;
                // don't wait for the scheduled tasks to complete
                executor.shutdownNow();
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy