I'm using RXTX to read data from a serial port. The reading is done within a thread spawned in the following manner:
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(port);
CommPort comm = portIdentifier.open("Whatever", 2000);
SerialPort serial = (SerialPort)comm;
...settings
Thread t = new Thread(new SerialReader(serial.getInputStream()));
t.start();
The SerialReader class implements Runnable and just loops indefinitely, reading from the port and constructing the data into useful packages before sending it off to other applications. However, I've reduced it down to the following simplicity:
public void run() {
ReadableByteChannel byteChan = Channels.newChannel(in); //in = InputStream passed to SerialReader
ByteBuffer buffer = ByteBuffer.allocate(100);
while (true) {
try {
byteChan.read(buffer);
} catch (Exception e) {
System.out.println(e);
}
}
}
When a user clicks a stop button, the following functionality fires that should in theory close the input stream and break out of the blocking byteChan.read(buffer) call. The code is as follows:
public void stop() {
t.interrupt();
serial.close();
}
However, when I run this code, I never get a ClosedByInterruptException, which SHOULD fire once the input stream closes. Furthermore, the execution blocks on the call to serial.close() -- because the underlying input stream is still blocking on the read call. I've tried replacing the interrupt call with byteChan.close(), which should then cause an AsynchronousCloseException, however, I'm getting the same results.
Any help on what I'm missing would be greatly appreciated.
You can't make a stream that doesn't support interruptible I/O into an InterruptibleChannel simply by wrapping it (and, anyway, ReadableByteChannel doesn't extend InterruptibleChannel).
You have to look at the contract of the underlying InputStream. What does SerialPort.getInputStream() say about the interruptibility of its result? If it doesn't say anything, you should assume that it ignores interrupts.
For any I/O that doesn't explicitly support interruptibility, the only option is generally closing the stream from another thread. This may immediately raise an IOException (though it might not be an AsynchronousCloseException) in the thread blocked on a call to the stream.
However, even this is extremely dependent on the implementation of the InputStream—and the underlying OS can be a factor too.
Note the source code comment on the ReadableByteChannelImpl class returned by newChannel():
private static class ReadableByteChannelImpl
extends AbstractInterruptibleChannel // Not really interruptible
implements ReadableByteChannel
{
InputStream in;
⋮
The RXTX SerialInputStream (what is returned by the serial.getInputStream() call) supports a timeout scheme that ended up solving all my problems. Adding the following before creating the new SerialReader object causes the reads to no longer block indefinitely:
serial.enableReceiveTimeout(1000);
Within the SerialReader object, I had to change a few things around to read directly from the InputStream instead of creating the ReadableByteChannel, but now, I can stop and restart the reader without issue.
i am using the code below to shutdown rxtx. i run tests that start them up and shut them down and the seems to work ok. my reader looks like:
private void addPartsToQueue(final InputStream inputStream) {
byte[] buffer = new byte[1024];
int len = -1;
boolean first = true;
// the read can throw
try {
while ((len = inputStream.read(buffer)) > -1) {
if (len > 0) {
if (first) {
first = false;
t0 = System.currentTimeMillis();
} else
t1 = System.currentTimeMillis();
final String part = new String(new String(buffer, 0, len));
queue.add(part);
//System.out.println(part + " " + (t1 - t0));
}
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
//System.out.println(Thread.currentThread().getName() + " interrupted " + e);
break;
}
}
} catch (IOException e) {
System.err.println(Thread.currentThread().getName() + " " + e);
//if(interruSystem.err.println(e);
e.printStackTrace();
}
//System.out.println(Thread.currentThread().getName() + " is ending.");
}
thanks
public void shutdown(final Device device) {
shutdown(serialReaderThread);
shutdown(messageAssemblerThread);
serialPort.close();
if (device != null)
device.setSerialPort(null);
}
public static void shutdown(final Thread thread) {
if (thread != null) {
//System.out.println("before intterupt() on thread " + thread.getName() + ", it's state is " + thread.getState());
thread.interrupt();
//System.out.println("after intterupt() on thread " + thread.getName() + ", it's state is " + thread.getState());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + " was interrupted trying to sleep after interrupting" + thread.getName() + " " + e);
}
//System.out.println("before join() on thread " + thread.getName() + ", it's state is " + thread.getState());
try {
thread.join();
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + " join interruped");
}
//System.out.println(Thread.currentThread().getName() + " after join() on thread " + thread.getName() + ", it's state is" + thread.getState());
}
Related
I'm writing Code for a Network Application. Therefor I'm using a LinkedBlockingQueue to store incoming messaged until they are consumed. The following code runs in it's own Thread and fills up the Queue:
while(true) {
String msg = in.readLine();
if(msg == null) continue;
recieveQueue.offer(msg);
System.out.println("recieveQueue.offer() called at: " + System.currentTimeMillis() + " hash:" + recieveQueue.hashCode());
System.out.println("Server recieved: " + msg.replace("\n", ""));
break;
}
Next I wrote a Method, which runs in the same "Main-Thread" (No extra Thread is created for this Method). It's only called when the stored Elements have to be consumed. It looks like the following:
public String recieveMessage() {
try {
System.out.println("recieveQueue.take() called at: " + System.currentTimeMillis() + " hash:" + recieveQueue.hashCode());
return recieveQueue.take();
}catch(InterruptedException e) {
e.printStackTrace();
return null;
}
}
When running this Code I get the following output:
recieveQueue.offer() called at: 1594558123030 hash:2091496189
Server recieved: CONFIRMED
recieveQueue.take() called at: 1594558123031 hash:2091496189
The hash verifies that I'm working on the same Queue, and as seen by the Time, recieveQueue.offer(msg) is definitely called before take() and so the Queue should contain a message. But the Program stops at the take() call. No Exceptions were thrown and there is no other point in the code where take() gets called. I waited for like 10 minutes but the take() call never finishes
Made few changes in your program.
Note: Please check in your code Consumer in while loop.
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class Main
{
public static void main(String[] args) {
BlockingQueue recieveQueue = new LinkedBlockingQueue<String>(10);
new Thread(){
public void run(){
int count=0;
while(true) {
count++;
String msg = "AAA:"+count;
if(msg == null) continue;
recieveQueue.offer(msg);
System.out.println("recieveQueue.offer() called at: " + System.currentTimeMillis() + " hash:" + recieveQueue.hashCode());
System.out.println("Server recieved: " + msg.replace("\n", ""));
}
}
}.start();
while(true){
try {
System.out.println("recieveQueue.take() called at: " + System.currentTimeMillis() + " hash:" + recieveQueue.hashCode());
System.out.println("recieveQueue.take() : "+recieveQueue.take());
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
For learning purposes, I am implementing UDP with the mechanisms of TCP (so that it guarantees safe transfer).
The Semaphore I am using is binary, so its sem = new Semaphore(1);.
I use this semaphore to control the entrance for my sendBuf, which is a List containing all packages which have been send, but not yet confirmed. Since I sometimes remove packages out of it when I get an ACK, I need to make sure I am not iterating with one thread while another thread is deleting something out of it.
The thing which is really bugging me is this:
public void timeoutTask(long seqNum) {
System.out.println("Timeout for package with SeqNum " + seqNum
+ " happened.");
timeoutValue *= 2;
try {
System.out.println("Acquire? in timeouttask");
sem.acquire();
System.out.println("Acquired! in timeouttask");
} catch (InterruptedException e1) {
System.out.println("semaphore not acquired");
e1.printStackTrace();
}for (FCpacket packet : sendBuf) {
System.out.println("Iterating!");
if (packet.getSeqNum() == seqNum) {
System.out.println("Package for seqNum " + seqNum + " found!");
reSendData = packet.getSeqNumBytesAndData();
DatagramPacket reSendPacket = new DatagramPacket(reSendData,
reSendData.length, hostaddress, SERVER_PORT);
try {
clientSocket.send(reSendPacket);
System.out.println("Packet with seq " + seqNum
+ " send again");
packet.setTimestamp(0);
startTimer(packet);
new ReceiveHandler(reSendData, reSendData.length,
clientSocket, rcvData, UDP_PACKET_SIZE, this).run();
} catch (IOException e) {
System.out.println("Couldn't send package");
e.printStackTrace();
}
}
}
sem.release();
System.out.println("released! in timeouttask");
Console output gives me the following:
Acquire? in timeouttask
Acquired! in timeouttask
Iterating!
Paket for seqNum 1 found!
Packet with seq 1 send again
So it gets the semaphore, starts iterating, it even sends the package, so by now it should Either: Iterate again ("iterating!") OR release the semaphore. None of the above happens, it is just stuck. I have no idea why - any ideas?
If ReceiveHandler is a Thread, it should be invoked as
new ReceiveHandler(reSendData, reSendData.length, clientSocket, rcvData, UDP_PACKET_SIZE, this).start();
But if it is a Runnable, it should be invoked as
new Thread(new ReceiveHandler(reSendData, reSendData.length, clientSocket, rcvData, UDP_PACKET_SIZE, this)).start();
run() will not execute the task in a separate Thread.
see: What's the difference between Thread start() and Runnable run()
public class MultiThreadExample extends Thread {
public static int count=0;
static String s="";
synchronized public static String read(){
String line="";
System.out.println("Enter new line:");
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
try {
line=br.readLine();
count++;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return line;
}
synchronized public static void write(String line){
try {
BufferedWriter br=new BufferedWriter(new FileWriter("C://name.txt"));
br.write(line);
System.out.println(line);
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run(){
if(count==0){
System.out.println("Read " + s + " Count " + count);
s=read();
System.out.println("Read " + s + " Count " + count);
}
else{
write(s);
System.out.println("Write" + s + " Count " + count);
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
MultiThreadExample th1=new MultiThreadExample();
MultiThreadExample th2=new MultiThreadExample();
th1.start();
th2.start();
}
}
The count check in run() method is not working. Any idea why? The count increases with each call, I can see, but the check is not working, and each time the control passes to read() method, and does not go to write()
What am I doing wrong? Also, is there any other efficient way to call multiple methods from a two threads, depending on situation?
P.S. I am trying to read input using one thread, and write the input value to a file in another thread
try this:
MultiThreadExample th1=new MultiThreadExample();
MultiThreadExample th2=new MultiThreadExample();
th1.start();
try {
th1.join();
} catch (InterruptedException ex) {
System.out.println(ex.getMessage());
}
th2.start();
Don't create a new BufferedReader for every line. Use the same one for the life of the socket. You're losing data read-ahead by each BufferedReader.
Remove all the static except main method ... All you need to ensure is that read and write don't change/read "count" at the same time ... Use a different lock object like "lockObject" and use wait() and notify(). You are looking for a producer/consumer sort of a pattern here. Here is an example: http://www.programcreek.com/2009/02/notify-and-wait-example/
can also try 'similar' approach. , which ever thread enters first reads, and the later one waits for the former to read and then it writes. (it doesn't need your static methods to be synchronized)
static ReentrantLock l = new ReentrantLock();
public void run(){
l.lock();
if(count==0){
System.out.println("Read " + s + " Count " + count);
s=read();
l.unlock();
System.out.println("Read " + s + " Count " + count);
}
else{
write(s);
System.out.println("Write" + s + " Count " + count);
}
}
Okay, can you please explain to me, why my previous code was not working, and the check failed?
#Shail016 explained it in a comment on your question. Here's one possible sequence of events.
main thread calls th1.start(), calls th2.start(), and then exits.
thread 1 enters the run() method, sees that count==0, enters the read() method, calls System.out.println(...)
thread 2 enters the run() method, sees that count==0, tries to enter the read() method, gets blocked, waiting for the mutex.
thread 1 returns from the System.out.println(...) call, reads a line, increments count, and returns,
thread 2 is allowed in to read(), etc., etc.,
etc.
etc.
Mark count as volatile. This ensures that changes from one thread are seen by other threads. As long as only one thread updates count, this is OK, otherwise, you could use either an AtomicInteger, an AtomicIntegerFieldUpdater in conjunction with a volatile field or (if you measure high contention, which is unlikely in your case) a LongAdder (all classes are from the java.util.concurrent.atomic package, the last is only available in Java 8).
I have the following code that runs a process and I want to know if there was an exception while running it. It hangs for no reason
Runtime runtime = Runtime.getRuntime();
proc = runtime.exec(command.toString());
ProcessHandler errorStream = new ProcessHandler(proc.getErrorStream(),"ERROR", rdyFilePath);
ExecutorService pool = Executors.newSingleThreadExecutor();
Future future = pool.submit(errorStream);
pool.shutdown();
try {
if(future.get() == null) {
log.info("Done completing error thread");
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
Here is the class for process handler
public class ProcessHandler implements Callable<Integer> {
private static Logger log = Logger.getLogger(ProcessHandler.class.getName());
InputStream inpStr;
String strType;
String rdyFile;
public ProcessHandler(InputStream inpStr, String strType, String rdyFile) {
this.inpStr = inpStr;
this.strType = strType;
this.rdyFile = rdyFile;
}
public Integer call() throws FileMetadataException {
StringBuffer sb = new StringBuffer();
try {
InputStreamReader inpStrd = new InputStreamReader(inpStr);
BufferedReader buffRd = new BufferedReader(inpStrd);
String line = null;
while((line = buffRd.readLine()) != null) {
if("ERROR".equalsIgnoreCase(strType)) {
sb.append(line + "\n");
log.info(strType + "->" + line);
}
}
if(sb != null) {
log.info("Error Stream length : " + sb.length());
throw new RuntimeException();
}
buffRd.close();
} catch(IOException e) {
log.error("IOException in ProcessHandler Thread" + e.fillInStackTrace());
System.err.println(e);
throw new FileMetadataException();
} finally {
if(sb != null) {
if(sb.toString().length() > 0 ) {
log.error("Error string buffer length " + sb.length());
// do not create rdy file
} else {
log.error("Error string buffer length : " + sb.length());
File f = new File(rdyFile);
try {
f.createNewFile();
} catch(IOException e) {
log.error("IOException while creating rdy file");
}
}
// create rdy file.
}
}
return sb.length();
}
}
}
I have the following code that runs a process and I want to know if there was an exception while running it. It hangs for no reason
If there was an exception your future.get() should have thrown with an ExecutionException -- it would not "hang". Are you sure that your exception is not being printed but somehow lost in the logs or console output?
In tracing your code, I see no way for your program to not finish after it finishes reading the stream. Maybe the process whose error-stream you are reading from is still running and the InputStream has not been closed yet? Maybe there is so much output that you are filling up core with the StringBuffer (which should be changed to a StringBuilder btw).
Can you attach to your application with jconsole to see if the thread is still running and if it is, what is it doing?
if(future.get() == null) {
log.info("Done completing error thread");
}
So this will only log output if you return null from your call() method. That will never happen since the only return is return sb.length();. So either you will get an exception from your call() or your result will be a non-null Integer.
From the Process javadoc:
Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock.
Per this warning, your future.get() method is hanging because you are only consuming the error stream from the process object. On all platforms I have ever utilized Process objects, I have observed that you need to consume both the Error and Standard out streams.
This is a good tool that uses a multithreaded approach to ensure that streams of a process are consumed.
In this case, since it appears that you don't care about the standard output of the process you might add something like this, borrowing the StreamHelper class:
StreamHelper inStreamHelper = new StreamHelper(proc.getInputStream());
inStreamHelper.start();
I'm writing my first non-trivial Java app that uses:
networking
a GUI
threads
It's a IM program. When I send a message, the server doesn't output what it should. I'm sorry this description is so bad, but I don't know how to narrow the problem down further.
public class MachatServer {
//snip
public static void sendMessage(int targetId, int fromId, String message) {
ConnectedClient targetClient = getClient(targetId);
// Also runs
System.out.println("Sending message: " + message + "\n\nfrom " + fromId + " to " + targetId);
targetClient.addOutCommand("/message:" + fromId + ":" + message + "\n");
}
}
class ConnectedClient implements Runnable {
public void run() {
String contact;
contact = s.getInetAddress().toString();
System.out.println("Connected to " + contact);
try {
out.write("/connected" + "\n");
out.flush();
String command;
while(true) {
if(shouldExit) {
s.close();
break;
}
if(in.hasNextLine()) {
command = in.nextLine();
commandProcessor.addInCommand(command);
}
Thread.sleep(100);
}
} catch(Exception e) {
e.printStackTrace();
}
}
// snip
public void addOutCommand(String command) {
commandProcessor.addOutCommand(command);
//
// My guess is that the problem is with this method as the next line
// Does not print out.
//
//
System.out.println("" + thisId + " recieved to send: " + command);
}
}
class CommandProcessor implements Runnable {
// snip
public void run() {
String currentCommandIn;
String currentCommandOut;
while(true) {
try {
currentCommandIn = inQueue.poll();
if(currentCommandIn != null) {
System.out.println("Processing: " + currentCommandIn);
String[] commandArr = CommandParser.parseRecievedCommand(currentCommandIn);
if(commandArr[0].equalsIgnoreCase("message")) {
int target = Integer.parseInt(commandArr[1]);
String message = commandArr[2];
// This definetly runs
System.out.println("Message sending to: " + target);
MachatServer.sendMessage(target, this.conId, message);
} else if(commandArr[0].equalsIgnoreCase("quit")) {
// Tell the server to disconnect us.
MachatServer.disconnect(conId);
break;
}
currentCommandOut = outQueue.poll();
if(currentCommandOut != null) {
try {
out.write(currentCommandOut + "\n");
System.out.println(currentCommandOut + "sent");
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
} catch(Exception e) {
e.printStackTrace();
}
public synchronized void addOutCommand(String command) {
if(command != null) {
try {
outQueue.push(command);
} catch(Exception e) {
System.out.println(command);
e.printStackTrace();
}
// Does not print
System.out.println("Ready to send: " + command);
} else {
System.out.println("Null command recieved");
}
//snip
}
The full source code is at my github, in case I have narrowed the problem down incorrectly.
The expected output should be when I telnet in and send "/message:0:test", it should send "/message:myid:test" to the client with ID 0. The actual output is nothing.
This is probably not a complete answer, but there are a few serious issues with your code that could be the cause of your problem, so you should fix those first.
First, the loop in CommandProcessor.run is busy-waiting, i.e., it runs constantly. You should use blocking operations. Also, inQueue and outQueue are accessed from two different threads so you need synchronization on every access. I recommend using something implementing the java.util.concurrent.BlockingQueue interface to solve both issues. And finally, when checking your full code, it appears that you also need to synchronize access to the ConnedtedClient.shouldExit field (I believe you can use `java.util.concurrent.atomic.AtomicBoolean as a replacement but I'm not sure).
And the reason why this could be the cause of your problem: Since CommandProcessor.run is not synchronizing on anything (or accessing anything volatile), the Java virtual machine can assume that nothing from outside can modify anything it examines, so in theory, when the run method first notices that inQueue and outQueue are both empty, it can optimize the whole method into nothing, as it can assume that it is the only thing that can modify them. But I don't know whether this can actually happen in practice, as the JVM needs to know quite a bit about the LinkedList implementation and notice that the thread is just doing these two checks in a loop. But it's always best to be safe because that way your code is guaranteed to work.
The field outQueue is uninitialized in CommandProcessor, and you commented out the printStackTrace() that would have helped you figure it out.
Maybe the problem is that the data you send is to short....
A friend of mine had a similar problem a couple of years ago, and it turned out the data was being buffered until it had enough data to send...
It had something to do with optimizing the amount of network traffic... I believe he mentioned something called "Nagle's algorithm" when he finally solved it....
Hope this can be of some help...