Pi4J / pi4j-v1

DEPRECATED Java I/O library for Raspberry Pi (GPIO, I2C, SPI, UART)

Home Page:http://www.pi4j.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Exception in thread "main" java.util.concurrent.RejectedExecutionException

atael opened this issue · comments

Hello,
I have written up a little program (well modified one I saw on pi4j.com) using Pi4J-0.0.5 (downloaded here: http://code.google.com/p/pi4j/downloads/detail?name=pi4j-0.0.5-SNAPSHOT.zip) and run into an issue which I am not sure how to debug or correct?

My environment is:


pi@raspberrypi ~ $ java -version
java version "1.7.0_10"
Java(TM) SE Embedded Runtime Environment (build 1.7.0_10-b18, headless)
Java HotSpot(TM) Embedded Client VM (build 23.6-b04, mixed mode)
pi@raspberrypi ~ $ uname -a
Linux raspberrypi 3.2.27+ #250 PREEMPT Thu Oct 18 19:03:02 BST 2012 armv6l GNU/Linux
pi@raspberrypi ~ $

The error looks like this:


Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask@3aa59d rejected from java.util.concurrent.ScheduledThreadPoolExecutor@4f1ada[Shutting down, pool size = 1, active threads = 0, queued tasks = 1, completed tasks = 0]
        at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2013)
        at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:816)
        at java.util.concurrent.ScheduledThreadPoolExecutor.delayedExecute(ScheduledThreadPoolExecutor.java:325)
        at java.util.concurrent.ScheduledThreadPoolExecutor.schedule(ScheduledThreadPoolExecutor.java:546)
        at com.pi4j.io.gpio.impl.GpioScheduledExecutorImpl.createCleanupTask(GpioScheduledExecutorImpl.java:80)
        at com.pi4j.io.gpio.impl.GpioScheduledExecutorImpl.pulse(GpioScheduledExecutorImpl.java:141)
        at com.pi4j.io.gpio.impl.GpioPinImpl.pulse(GpioPinImpl.java:297)
        at com.pi4j.io.gpio.impl.GpioPinImpl.pulse(GpioPinImpl.java:262)
        at com.pi4j.io.gpio.impl.GpioPinImpl.pulse(GpioPinImpl.java:252)
        at atael.Pi4JGPIOPins.main(Pi4JGPIOPins.java:50)

And the code looks like this:


package atael;

import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalOutput;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.RaspiPin;

public class Pi4JGPIOPins {

    public static void main(String[] args) throws InterruptedException {
        // create gpio controller
        final GpioController gpio = GpioFactory.getInstance();
        
        final GpioPinDigitalOutput GPIOPinOut[] =  {
            gpio.provisionDigitalOutputPin(RaspiPin.GPIO_00, PinState.LOW),
            gpio.provisionDigitalOutputPin(RaspiPin.GPIO_01, PinState.LOW),
            gpio.provisionDigitalOutputPin(RaspiPin.GPIO_02, PinState.LOW),
            gpio.provisionDigitalOutputPin(RaspiPin.GPIO_03, PinState.LOW),
            gpio.provisionDigitalOutputPin(RaspiPin.GPIO_04, PinState.LOW),
            gpio.provisionDigitalOutputPin(RaspiPin.GPIO_05, PinState.LOW),
            gpio.provisionDigitalOutputPin(RaspiPin.GPIO_06, PinState.LOW),
            gpio.provisionDigitalOutputPin(RaspiPin.GPIO_07, PinState.LOW),
            gpio.provisionDigitalOutputPin(RaspiPin.GPIO_08, PinState.LOW),
            gpio.provisionDigitalOutputPin(RaspiPin.GPIO_09, PinState.LOW),
            gpio.provisionDigitalOutputPin(RaspiPin.GPIO_10, PinState.LOW),
            gpio.provisionDigitalOutputPin(RaspiPin.GPIO_11, PinState.LOW),
            gpio.provisionDigitalOutputPin(RaspiPin.GPIO_12, PinState.LOW),
            gpio.provisionDigitalOutputPin(RaspiPin.GPIO_13, PinState.LOW),
            gpio.provisionDigitalOutputPin(RaspiPin.GPIO_14, PinState.LOW),
            gpio.provisionDigitalOutputPin(RaspiPin.GPIO_15, PinState.LOW),
            gpio.provisionDigitalOutputPin(RaspiPin.GPIO_16, PinState.LOW)
        };
        
        gpio.setShutdownOptions(true, PinState.LOW, GPIOPinOut);
        
        while (true) {
            for (int i = 0; i <= 16; i++) {
                GPIOPinOut[i].pulse(50);
                Thread.sleep(50);
                System.out.print(i + " ");
            }
        }      
    }
}

Any idea what could be wrong?

Thanks,
Andy

Hi Andy, some of the program code got cut off, can you please paste the rest of it (or link to it if you have it in a public repository). Thanks, Robert

Hello,
don't understand why the code got cut off but here it is:

package atael;

import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalOutput;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.RaspiPin;

public class Pi4JGPIOPins {

public static void main(String[] args) throws InterruptedException {

    final GpioController gpio = GpioFactory.getInstance();

    final GpioPinDigitalOutput GPIOPinOut[] =  {
        gpio.provisionDigitalOutputPin(RaspiPin.GPIO_00, PinState.LOW),
        gpio.provisionDigitalOutputPin(RaspiPin.GPIO_01, PinState.LOW),
        gpio.provisionDigitalOutputPin(RaspiPin.GPIO_02, PinState.LOW),
        gpio.provisionDigitalOutputPin(RaspiPin.GPIO_03, PinState.LOW),
        gpio.provisionDigitalOutputPin(RaspiPin.GPIO_04, PinState.LOW),
        gpio.provisionDigitalOutputPin(RaspiPin.GPIO_05, PinState.LOW),
        gpio.provisionDigitalOutputPin(RaspiPin.GPIO_06, PinState.LOW),
        gpio.provisionDigitalOutputPin(RaspiPin.GPIO_07, PinState.LOW),
        gpio.provisionDigitalOutputPin(RaspiPin.GPIO_08, PinState.LOW),
        gpio.provisionDigitalOutputPin(RaspiPin.GPIO_09, PinState.LOW),
        gpio.provisionDigitalOutputPin(RaspiPin.GPIO_10, PinState.LOW),
        gpio.provisionDigitalOutputPin(RaspiPin.GPIO_11, PinState.LOW),
        gpio.provisionDigitalOutputPin(RaspiPin.GPIO_12, PinState.LOW),
        gpio.provisionDigitalOutputPin(RaspiPin.GPIO_13, PinState.LOW),
        gpio.provisionDigitalOutputPin(RaspiPin.GPIO_14, PinState.LOW),
        gpio.provisionDigitalOutputPin(RaspiPin.GPIO_15, PinState.LOW),
        gpio.provisionDigitalOutputPin(RaspiPin.GPIO_16, PinState.LOW)
    };

    gpio.setShutdownOptions(true, PinState.LOW, GPIOPinOut);

    while (true) {
        for (int i = 0; i <= 16; i++) {
            GPIOPinOut[i].pulse(50);
            Thread.sleep(50);
            System.out.print(i + " ");
        }
    }
}

}

On Sun, Jan 27, 2013 at 10:48 AM, Robert Savage notifications@github.comwrote:

Hi Andy, some of the program code got cut off, can you please paste the
rest of it (or link to it if you have it in a public repository). Thanks,
Robert


Reply to this email directly or view it on GitHubhttps://github.com//issues/31#issuecomment-12757020.

The class GpioScheduledExecutorImpl creates a ThreadPoolExecutor with a queue size of 5
scheduledExecutorService = Executors.newScheduledThreadPool(5);

You are submitting 16 jobs to the queue. The queue will be full after submitting only 5 jobs, then the Executor will start rejecting jobs.

It would seem to me that the size of the Executors queue should be at least equal to the number of gpio pins.

You could change the size of the Executors queue in the pi4j code or you could use this code, which would need to go into it's own thread to be useful.

this code doesn't quite do what you had coded, but I think it does what you intended - 50ms on then 50ms off on all pins.

while(true)
{
for (int i = 0; i <= 16; i++)
{
GPIOPinOut[i].high();
}
Thread.sleep(50); System.out.print(i + " ");
for (int i = 0; i <= 16; i++)
{
GPIOPinOut[i].low();
}
Thread.sleep(50); System.out.print(i + " ");
}

I am working on the scheduled executors issue.

Another workaround may be to use the new blocking pulse function that was added in 0.0.5-SNAPSHOT.
(https://github.com/Pi4J/pi4j/blob/develop/pi4j-core/src/main/java/com/pi4j/io/gpio/GpioPinDigitalOutput.java#L48)

GPIOPinOut[i].pulse(50);
Thread.sleep(50);

Since you are pulsing for 50 ms and then sleeping for 50 ms, I think this could be simplified using this single line and removing the sleep statement. The "true" argument will cause the pulse to block for the pulse duration.

GPIOPinOut[i].pulse(50, true);

This pulse() blocking call does not use the scheduled executor and will return a null future object.
(https://github.com/Pi4J/pi4j/blob/develop/pi4j-core/src/main/java/com/pi4j/io/gpio/impl/GpioPinImpl.java#L275)

The real issue of limited thread needs to be addressed in the project, but I think this will get it working for your particular situation.

Thanks, Robert

Robert,
thank you! The GPIOPinOut[i].pulse(50, true); seems to be right way to go for me and works like a charm. Now off to more challenging stuff...

--Andy

I am reopening the issue because the limited number of threads needs to be addressed in a future build.

Fixed in latest 0.0.5-SNAPSHOT (2013-02-09) build.

New build includes enough threads in the pool by default to handle all the RPi GPIO pins.
Also, there is a new ExecutorServiceFactory implementation that allow users to provide their own executor service factory where you can create the executors and manage your own thread pool.