【问题标题】:Java, MultiThreading, and Raspberry PiJava、多线程和树莓派
【发布时间】:2015-11-30 16:56:49
【问题描述】:

所以我的多线程部分工作。当我在编译后第一次运行我的程序时,它只运行 3 个线程中的 1 个或 2 个。然后立即再次运行它,它在所有线程都激活并运行的情况下运行得非常好。我想不出为什么所有线程都不会在第一次执行 java 类时运行,然后在第一次执行终止后开始执行该类的第二次执行。

我在 Raspberry Pi 2 上使用 Pi4j。我需要代码第一次运行良好,因为我试图在 Pi 启动时运行它。

这是我开始线程的地方。

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();
}

这就是线程正在运行的内容。线程正在传递我称之为门的值。

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){

    }

}

任何帮助将不胜感激。 谢谢

【问题讨论】:

  • 你说,“...它只运行 3 个线程中的 1 个或 2 个。”你怎么知道的?这段代码应该做什么?它实际上在做什么?到目前为止,您尝试过做什么来查明问题?
  • 你的线程除了注册一个事件处理程序之外什么都不做,然后while(true) sleep(500);你为什么要使用一个线程呢?
  • 您正在使用for 循环来测试p 是否在[0..2] 范围内。你不需要为此使用循环。
  • 我正在使用多线程来运行 3 个不同的磁门传感器,这样我就不必为每个传感器运行 3 个单独的类。这样,我有 1 个主类并运行 3 次,每次运行时调用不同的 gpio 端口。通过激活传感器然后检查数据库以查看是否记录了日志,我知道它何时起作用和不起作用。但是当我重新启动后第一次运行它时,所有线程都没有被激活。
  • 除了调用door.addListener(...),您的线程似乎没有做任何事情,然后永远休眠。为什么不让主线程添加监听器?永远沉睡的线程有什么用?

标签: java multithreading raspberry-pi2


【解决方案1】:

检查db:共享,使用时不受保护,在每个线程中创建。

结果可能无法预测。

我建议:

1 添加这个

 static final Object db_sync=new Object();

2 db只初始化一次,在DoorSwitch的构造函数中调用

static DBConnection db=null;

static db_initialize()
{

synchronized(db_sync)
 {
 if (db==null) 
    db = new DBConnection();//create a new object of database connection class
  }

}

3 环绕db的使用

synchronized(db_sync)
 {
  // Do what you want with db
  }

【讨论】:

  • 我对你在问什么感到困惑?
  • 他要求修复未同步的静态共享对象
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-04
  • 1970-01-01
  • 2014-02-23
  • 1970-01-01
  • 1970-01-01
  • 2014-12-09
  • 2013-11-05
相关资源
最近更新 更多