gpt4 book ai didi

java - 重入锁 - 尝试使用 rxtx 将字节 [] 写入串行端口时出现非法监控状态异常

转载 作者:行者123 更新时间:2023-11-30 09:24:16 25 4
gpt4 key购买 nike

我有以下代码给我带来了很多麻烦,我想我盯着它看的时间太长了,希望有新的眼睛-

调用方法-(在RobotInterface类中)

        try
{
serialConnection.put(candidate.getCandidate().getGenome());
TwoWaySerialCommTest.inputAvailable.await();
}
catch ( Exception e )
{
TwoWaySerialCommTest.listPorts();
e.printStackTrace();
}

TwoWaySerialCommTest 类 - 改编自 rxtx 网站示例。完整代码供引用,重要部分是put()方法和serialwriter。

     package org.dnsdojo.ryanhost.GA.MuPlusOne;

import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.locks.*;

/**
* This version of the TwoWaySerialComm example makes use of the
* SerialPortEventListener to avoid polling.
*
*/
public class TwoWaySerialCommTest
{
static Lock lock = new ReentrantLock();
static Condition outputAvailable = lock.newCondition();
static Condition inputAvailable = lock.newCondition();
public volatile byte[] inputBuffer = new byte[1024];
public volatile byte[] outputBuffer = new byte[1024];

public TwoWaySerialCommTest()
{
super();
}

public void put(byte[] buffer)
{
try
{
lock.lock();
int i = 0;
for(; i < buffer.length; i++ )
{
outputBuffer[i] = buffer[i];
}
System.out.println((byte) '\n');
outputBuffer[i] = (byte) '\n';
i++;
for(; i < outputBuffer.length; i++ )
{
outputBuffer[i] = 0;
}
System.out.println("Output buffer after put");
for(int j = 0; j < outputBuffer.length; j++)
{
System.out.print(outputBuffer[j]);
}

}
catch(Exception e)
{
System.out.println("Exception for lock in put");
e.printStackTrace();
}
finally
{
lock.unlock();
outputAvailable.signal();
}
}


void connect ( String portName ) throws Exception
{
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
if ( portIdentifier.isCurrentlyOwned() )
{
System.out.println("Error: Port is currently in use");
}
else
{
CommPort commPort = portIdentifier.open(this.getClass().getName(),2000);

if ( commPort instanceof SerialPort )
{
SerialPort serialPort = (SerialPort) commPort;
serialPort.setSerialPortParams(57600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);

InputStream in = serialPort.getInputStream();
OutputStream out = serialPort.getOutputStream();


serialPort.addEventListener(new SerialReader(in , inputBuffer));
serialPort.notifyOnDataAvailable(true);

(new Thread(new SerialWriter(out , outputBuffer))).start();

}
else
{
System.out.println("Error: Only serial ports are handled by this example.");
}
}
}

static void listPorts()
{
java.util.Enumeration<CommPortIdentifier> portEnum = CommPortIdentifier.getPortIdentifiers();
while(portEnum.hasMoreElements())
{
CommPortIdentifier portIdentifier = portEnum.nextElement();
if(portIdentifier == null)
{
System.out.println("No ports");
}
System.out.println("Available - " + portIdentifier.getName());
}
}

/**
* Handles the input coming from the serial port. A new line character
* is treated as the end of a block in this example.
*/
public static class SerialReader implements SerialPortEventListener
{
private InputStream in;
byte[] buffer;

public SerialReader ( InputStream in )
{
this.in = in;
}

public SerialReader (InputStream in, byte[] buffer)
{
this.in = in;
this.buffer = buffer;
}

public void serialEvent(SerialPortEvent arg0) {
lock.lock();
int data;

try
{

int len = 0;
while ( ( data = in.read()) > -1 )
{
if ( data == '\n' )
{
break;
}
buffer[len++] = (byte) data;
}
//inputAvailable.signal();
//outputAvailable.signal();
}
catch ( IOException e )
{
e.printStackTrace();
System.exit(-1);
}
finally
{
lock.unlock();
}
}

}

/** */
public static class SerialWriter implements Runnable
{
OutputStream out;
volatile byte[] buffer;

public SerialWriter ( OutputStream out )
{
this.out = out;
}

public SerialWriter ( OutputStream out, byte[] buffer)
{
this.out = out;
this.buffer = buffer;
}

public void run ()
{
while(true)
{
lock.lock();
try
{
outputAvailable.await();
System.out.println("Waking up");
int i = 0;
if (this.buffer != null)
{
System.out.println("Buffer isn't empty");
for (int j = 0; j < buffer.length; j++)
{
System.out.print(buffer[i]);
}
while(buffer[i] != ((byte)'\n') && i < buffer.length -1 )
{
this.out.write(buffer[i++]);
System.out.print(buffer[i-1]);
buffer[i-1] = 0;
}
}
else
{
System.out.println("Buffer is null");
System.out.println(this.buffer.toString());
}
}
catch ( IOException e )
{
e.printStackTrace();
System.exit(-1);
}
catch(Exception e)
{
e.printStackTrace();
}

finally
{

lock.unlock();
}
}
}
}



/* public static void main ( String[] args )
{
try
{
(new TwoWaySerialCommTest()).connect("/dev/ttyS82");
}
catch ( Exception e )
{
TwoWaySerialCommTest.listPorts();
e.printStackTrace();
}
}
*/

}

输出如下所示。我试过四处移动锁文件,从串行编写器中取出锁,在调用方法和其他一些技巧中加锁。

期望的结果是该方法将调用serialConnection(已连接的TwoWaySerialCommTest的实例),并等待serialConnection写入串口并收到响应,然后再继续执行。

几个小时以来我一直在努力解决这个问题,请帮忙:)

Output buffer after put
10101010000001101111010110101111010000100110101000000011101011100011000101111111010011101111001100111110001010011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000RXTX fhs_lock() Error: creating lock file: /var/lock/LCK..ttyS82: File exists
java.lang.IllegalMonitorStateException
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.signal(AbstractQueuedSynchronizer.java:1941)
at org.dnsdojo.ryanhost.GA.MuPlusOne.TwoWaySerialCommTest.put(TwoWaySerialCommTest.java:64)
at org.dnsdojo.ryanhost.GA.MuPlusOne.RobotInterface.evaluate(RobotInterface.java:35)
at org.dnsdojo.ryanhost.GA.MuPlusOne.RobotInterface.run(RobotInterface.java:58)
at java.lang.Thread.run(Thread.java:722)

如果我按照建议将通知移动到 try block 内,则输出为

Output buffer after put
11100111000111010010111111000110100010010111000000110001010011001001110001010111110001010110010001010001010110101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Waking up
Buffer isn't empty
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111RXTX fhs_lock() Error: creating lock file: /var/lock/LCK..ttyS82: File exists
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110011100011101001011111100011010001001011100000011000101001100100111000101011111000101011001000101000101011010java.lang.IllegalMonitorStateException
at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:155)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1260)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.fullyRelease(AbstractQueuedSynchronizer.java:1723)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2040)
at org.dnsdojo.ryanhost.GA.MuPlusOne.RobotInterface.evaluate(RobotInterface.java:36)
at org.dnsdojo.ryanhost.GA.MuPlusOne.RobotInterface.run(RobotInterface.java:58)
at java.lang.Thread.run(Thread.java:722)

RobotInterface 类 -

package org.dnsdojo.ryanhost.GA.MuPlusOne;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

public class RobotInterface implements Runnable
{
// create a serial connection
// transmit a string and check for response
// wait for evaluation
// take evaluation
private CandidateTest candidate;
private TwoWaySerialCommTest serialConnection;
//private Random rng = new Random();

protected static Logger logger = Logger.getLogger("Thread" + Thread.currentThread().getName());

public RobotInterface(CandidateTest test, TwoWaySerialCommTest serialConnection)
{
this.candidate = test;
this.serialConnection = serialConnection;
PropertyConfigurator.configure("log4j.properties");
}

public void evaluate (Genome genome)
{
//send to robot and return fitness
//genome.setFitness(rng.nextDouble());
logger.debug("fitness is " + genome.getFitness());
try
{
try
{

serialConnection.put(candidate.getCandidate().getGenome());
TwoWaySerialCommTest.inputAvailable.await();


}
catch ( Exception e )
{
TwoWaySerialCommTest.listPorts();
e.printStackTrace();
}
}
catch(Exception E)
{

}

}

public void run()
{
logger.debug("entering run of Robot Interface");
logger.debug("Send Genome via serial and wait for a response");
Genome testSubject = candidate.getCandidate();
evaluate(testSubject);
candidate.finished();
}

最佳答案

你在释放锁后调用signalyou should call it WHILE holding the lock :

lock.unlock();
outputAvailable.signal();

应该是相反的:

outputAvailable.signal();
lock.unlock();

尽管在 try block 的末尾调用 signal 会更好。

关于java - 重入锁 - 尝试使用 rxtx 将字节 [] 写入串行端口时出现非法监控状态异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15769220/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com