Brenn01
Posts: 1
Joined: Sun Nov 29, 2015 7:08 pm

Pi4j, Multi threading and Raspberry Pi

Sun Nov 29, 2015 7:13 pm

So I have my multi threading partially working. When I run my program the very first time after compiling it only runs 1 or 2 of the 3 threads. Then running it again right after, it runs perfectly fine with all of the threads activated and running. I can't think of any reason why all of the threads would not run on the first execution of the java class, and then start working on the second execution of the class after the first one has been terminated. The point of using the mulit threading is because, I want to have the door sensors constantly running in the background waiting for the sensor to register that the door is open or closed and it will then log it into the database for our records.

I don't understand why the thread starts in different orders when I have it labeled as 0, 1, 2 but it sometimes starts 1, 2, 0. Or why does it only start 1 thread on the first execution and not all 3 of them?

I am using Pi4j on a Raspberry Pi 2. I need the code to run fine the first time because I am trying to run this on bootup of the Pi.

This is where I start the threading.

Code: Select all

public class Doors {
public static void main(String[] args) {        
    Thread door1 = new Thread(new DoorSwitch(0));
    door1.start();
    Thread door2 = new Thread(new DoorSwitch(1));
    door2.start();
    Thread door3 = new Thread(new DoorSwitch(2));
    door3.start();
}
This is what the Thread is running. The threading is passing in the value of what I call the door.

Code: Select all

public class DoorSwitch implements Runnable{    
int p;
int doorID;
int tempPin;
static DBConnection db = new DBConnection();//create a new object of database connection class
public DoorSwitch(int currPin){
p = currPin;
    doorID = (p + 1);
}
public void run()
{
    try{
        final GpioController gpio = GpioFactory.getInstance();
        final GpioPinDigitalInput[] gpPins = {
                 gpio.provisionDigitalInputPin(RaspiPin.GPIO_28, PinPullResistance.PULL_UP),
                 gpio.provisionDigitalInputPin(RaspiPin.GPIO_29, PinPullResistance.PULL_UP),
                 gpio.provisionDigitalInputPin(RaspiPin.GPIO_27, PinPullResistance.PULL_UP),
         };
        for (int i=1; i<gpPins.length; i++){
            if(p == i){
                tempPin = p;
            }
        }
        final GpioPinDigitalInput door = gpPins[tempPin];
        door.addListener(new GpioPinListenerDigital() {
            @Override
            public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
                if(event.getState() == PinState.HIGH){
                    try{
                        db.dbConnection();
                        System.out.println(doorID);
                        System.out.println("Door Open! " + p);
                        String update = "UPDATE `door` SET `status`=" + 1 + " WHERE `id`="+ doorID +";";
                        db.getStatement().executeUpdate(update);
                        String log = "INSERT INTO `door_log` (`door_id`, `status`) VALUES ("+ doorID + ",1);";
                        db.getStatement().executeUpdate(log);
                    } catch (SQLException | ClassNotFoundException | InstantiationException | IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    }
                }
                if(event.getState() == PinState.LOW){
                    try{
                        db.dbConnection();
                        System.out.println(doorID);
                        System.out.println("                Door Closed! " + p);
                        String update = "UPDATE `door` SET `status`=" + 0 + " WHERE `id`="+ doorID +";";
                        db.getStatement().executeUpdate(update);
                        String log = "INSERT INTO `door_log` (`door_id`, `status`) VALUES ("+ doorID + ",0);";
                        db.getStatement().executeUpdate(log);
                    } catch (SQLException | ClassNotFoundException | InstantiationException | IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    }
                }
                //System.out.println(" --> GPIO PIN STATE CHANGE: " + event.getPin() + " = " + event.getState());
            } 
        });
        while(true) {
            Thread.sleep(500);
        }
        // stop all GPIO activity/threads by shutting down the GPIO controller
        // (this method will forcefully shutdown all GPIO monitoring threads and scheduled tasks)
        // gpio.shutdown();   <--- implement this method call if you wish to terminate the Pi4J GPIO controller
    }catch(Exception e){
    }
}

User avatar
savageautomate
Posts: 225
Joined: Thu Aug 16, 2012 3:20 pm
Location: USA
Contact: Website

Re: Pi4j, Multi threading and Raspberry Pi

Fri Dec 11, 2015 3:36 am

Hi Brenn01,

A couple of comments on the code.

You are provisioning the same GPIO pins over again with each new thread. I'm not sure what negative impact that may or may not result in, but I would advise against provisioning the same pins in separate threads. Either only provision the pins you need in each thread or provision all pins in your main and pass the pins to each thread class.

Also just so you know the "handleGpioPinDigitalStateChangeEvent" is a callback that is dispatched from an internal thread executor managed by the Pi4J library. So anything you place in that event handler is running in the context of Pi4J's thread executor. Only one event will be dispatched from the Pi4J thread pool at a time. So if you need to perform any long running operations such as database access, it will block the next GPIO event until your code returns. If this is the case or if you are looking for real multithreaded concurrency, you may want to handle the event and return as fast as possible and delegate any longer running/blocking operations to run under your own thread.

Thanks, Robert
Robert Savage | Follow me @savageautomate
http://www.pi4j.com | http://www.pislices.com
http://www.savagehomeautomation.com

Return to “Troubleshooting”