I have a problem caused by multi-threading and Android Open Accessory.
I need to communicate with a USB Accessory, but I need to do it from 2 threads. One thread generates and sends data the other one reads data.
Why I don't use a single thread? Because there can be 1 or more writes before a read and reads are blocking, so that is not an option.
If using multiple threads, I do run into "I/O Error (No such device)" sooner or later, because I will have a collision between read & write being executed at the same time.
Locking will more or less put me back in single-thread situation, so not good.
.available() method on the input-stream returns is not supported, so I cannot check if anything is available before doing a read
Since it's not a socket-based stream I cannot set timeout either.
I have tried getting the FileDescriptor from the USBAccessory and passing to JNI to handle it there, but after the first read/write the device becomes inaccessible.
Question/Suggestion needed:
What will be a suggested/best-practice approach to this? I do not expect written code, I just need some guidance on how to approach this problem.
To clarify:
The software at the other end might or might NOT respond with any data. There are some so called silent sends were the data sent it's just received but there is no ACK. Since the app I'm working on is only a proxy, I do not have a clear picture if the data will or will not produce an answer. That will require analysis of the data as well, which isn't on the books at the moment.
As you want to do read and write in parallel, writing will always lead to a pause to read if the read is on the same part as write.
May be you can follow similar approach as ConcurrentHashMap and use different locks for different segments and lock read only if write is on the same segment else allow the read to happen.
This will
Avoid blocking read during write in most scenarios
Avoid collision and
Definitely wont be a single thread approach.
Hope that helps.
If using multiple threads, I do run into I/O Error (No such device)
sooner or later, because I will have a collision between read & write
being executed at the same time.
This says it all. Since you are doing read and write on the same channel that does not support concurrent access, you are required to have your thread wait until the other thread is done doing read/write.
Your two-thread approach is what I would do, more or less. Good luck and trust in yourself.
Related
I'm experimenting with some network code, and I'm trying to figure out a good way to trigger writes to my DatagramChannel after having processed an event on a separate thread. This is quite simple for TCP, since you have a separate socket on which you can register your write interest (see reactor pattern, etc). For UDP, however, registering and deregistering interest with the datagram channel doesn't work so well, since I'm basically just modifying the same selection key.
I feel like you either block on the send in the event handler thread (wrong because then we're using blocking sends), or you block on a queue or something to take the responses and write them (also wrong because then we're blocking the selector thread).
I'd like to do something like switch the interest to write once I have something to write, and then back again to read, but then I run the risk of a race where I set it back to read after a write has been queued up, and then that write waits until I get the next read, which is also bad.
Yes, I know that there are other, potentially better suited threading models for these sorts of things, but I'm experimenting, so I'm curious. =)
You don't have to set the interest-ops to write when you want to write. Just write, from whatever thread you happen to be in. Only if that write returns zero do you need to worry about write interest-ops, as per many answers here.
I am trying to read data from 5 devices connected serially. My Java code is running fine if the device is healthy, if not then inputstream.read() hangs the program and does not allow further execution.
I have tried using inputstream.available(), BufferedInputStream... but nothing works.
What I want to do is: if a device does not respond my code, it should end itself and let the control go to the main program where it will go to the next device. The socket remains open for one cycle of polling.
Socket es = new Socket("10.12.90.153",4001);
OutputStream osnew= es.getOutputStream();
InputStream isnew = new BufferedInputStream(es.getInputStream());
This is done in the task program, then I pass osnew and isnew to each device at a gap of one second for further action. The osnew writes some data to which the device responds. Then I read from isnew...This where the program hangs.
InputStream is designed to block when you try and read data and none is available. You could call the available() method to see whether any data is available to read without blocking, but this only works one way - if available() returns non-zero you know you can read without blocking, but if it returns zero you won't necessarily be blocked. It is perfectly valid for an input stream to always return zero from available().
You may wish to look into the non-blocking I/O APIs of java.nio instead of using streams.
You could handle each device in a separate thread. That way your program will stay responsive even when the devices aren't. But be aware of the pitfalls of multithreaded programming.
More information about multi-threaded programming in Java can be found on http://docs.oracle.com/javase/tutorial/essential/concurrency/
How are you reading from the device? I'll assume you're using some form of FileInputStream to do it. That class looks to be suitable for reading from a filesystem to me, but a device, which could block for a long period of time is likely to lock up the Java thread until the device does respond. You need to make some kind of timed read request of the device, and I don't know of any Java class that does that.
Best suggestion I have is to write some JNI code that talks nicely and doesn't block when your devices stop responding. This is what I did when I was talking to a USB device. If I were coding this (for Linux) I would use select (which has a time period argument) to wait of an input from any of the devices.
This question is semi-theory, semi-how to properly code.
I am thinking about making an app in Java that will accepted streaming data, and as the data comes in, update a GUI.
So, what I am thinking of doing is just spawning off threads in Java that will:
collect data for X-milliseconds,
Take new data and update GUI with it
At the same time, start a new thread, collecting data for X milliseconds
This new thread must start off right where the first thread began
And, at the same time, all other parts of the program around going on in their own threads too.
So I need to make sure the threads don't collide, no data is lost in the mix, and I need to have an understanding of the speed limits. Say if the data is coming in at 1 Gbs vs 1 Mbs, what programming difference does that make?
The specific application includes data coming in from bluetooth and also data coming in from the Internet via an HTTPS rest API
If anyone has examples, either online or something quick and dirty right here, that'd be great. My Google searches came up dry..
The question is rather broad, but from an archtetctural point of view, I think the complexity decreases greatly if you change it to one thread reading from your device and putting the data into a buffer and one thread reading from that buffer and updating the UI. This reduces the code that needs to take care of multiple threads accessing it at the same time (idealy it reduces it to the buffer you use) and make synchronization much easier. It also decouples the fetching of the data from displaying it.
Writing the buffer can start off with using PipedInputStream and PipedOutputStream, however in one of my projects it turned out not to be fast enough if you really want to provide real-time processing and display, so you might end up writing yourself a low-latency buffer class.
I'm writing a simple application for an android phone to communicate with a PC over a socket connection.
The phone might write or recieve a message at any time, and the computer might as well.
The solution I have used so far works like this:
Create a thread and call READ in it.
Run an infinte loop.
Check if thread has finished,
If so grab the READ and process,
Then start a new thread also calling read.
Check to see if another object working in another thread wants to write,
If so grab and write.
Specifically, I am using AsyncTask from the Android API to run the threads.
It all works fine, but I am wondering if creating a new thread for each READ is too performance heavy and/or bad coding, and if so how I can reuse the same thread to have the same behaviour.
Alternatively, is there a better way to handle this situation overall?
Thanks in advance for any advice!
Yes, creating a new thread for each read is grossly inefficient for your described need.
Instead, consider creating a single thread, a List<your data type> to hold reads, and a semaphore to flag that data is available. Your thread reads each message, places it into the list, and posts the semaphore to whatever is waiting for data. That 'whatever' then receives whatever is in the list until it empties it, then goes back to waiting on the semaphore.
You need one read thread and one write thread. Both should use a BlockingQueue to interface with the rest of the application. Although I don't understand why you would have multiple threads wanting to write.
Sometimes, while sending a large amount of data via SocketChannel.write(), the underlying TCP buffer gets filled up, and I have to continually re-try the write() until the data is all sent.
So, I might have something like this:
public void send(ByteBuffer bb, SocketChannel sc){
sc.write(bb);
while (bb.remaining()>0){
Thread.sleep(10);
sc.write(bb);
}
}
The problem is that the occasional issue with a large ByteBuffer and an overflowing underlying TCP buffer means that this call to send() will block for an unexpected amount of time. In my project, there are hundreds of clients connected simultaneously, and one delay caused by one socket connection can bring the whole system to a crawl until this one delay with one SocketChannel is resolved. When a delay occurs, it can cause a chain reaction of slowing down in other areas of the project, and having low latency is important.
I need a solution that will take care of this TCP buffer overflow issue transparently and without causing everything to block when multiple calls to SocketChannel.write() are needed. I have considered putting send() into a separate class extending Thread so it runs as its own thread and does not block the calling code. However, I am concerned about the overhead necessary in creating a thread for EACH socket connection I am maintaining, especially when 99% of the time, SocketChannel.write() succeeds on the first try, meaning there's no need for the thread to be there. (In other words, putting send() in a separate thread is really only needed if the while() loop is used -- only in cases where there is a buffer issue, perhaps 1% of the time) If there is a buffer issue only 1% of the time, I don't need the overhead of a thread for the other 99% of calls to send().
I hope that makes sense... I could really use some suggestions. Thanks!
Prior to Java NIO, you had to use one Thread per socket to get good performance. This is a problem for all socket based applications, not just Java. Support for non-blocking IO was added to all operating systems to overcome this. The Java NIO implementation is based on Selectors.
See The definitive Java NIO book and this On Java article to get started. Note however, that this is a complex topic and it still brings some multithreading issues into your code. Google "non blocking NIO" for more information.
The more I read about Java NIO, the more it gives me the willies. Anyway, I think this article answers your problem...
http://weblogs.java.net/blog/2006/05/30/tricks-and-tips-nio-part-i-why-you-must-handle-opwrite
It sounds like this guy has a more elegant solution than the sleep loop.
Also I'm fast coming to the conclusion that using Java NIO by itself is too dangerous. Where I can, I think I'll probably use Apache MINA which provides a nice abstraction above Java NIO and its little 'surprises'.
You don't need the sleep() as the write will either return immediately or block.
You could have an executor which you pass the write to if it doesn't write the first time.
Another option is to have a small pool of thread to perform the writes.
However, the best option for you may be to use a Selector (as has been suggested) so you know when a socket is ready to perform another write.
For hundreds of connections, you probably don't need to bother with NIO. Good old fashioned blocking sockets and threads will do you.
With NIO, you can register interest in OP_WRITE for the selection key, and you will get notified when there is room to write more data.
There are a few things you need to do, assuming you already have a loop using
Selector.select(); to determine which sockets are ready for I/O.
Set the socket channel to non-blocking after you've created it, sc.configureBlocking(false);
Write (possibly parts of) the buffer and check if there's anything left. The buffer itself takes care of current position and how much is left.
Something like
sc.write(bb);
if(sc.remaining() == 0)
//we're done with this buffer, remove it from the select set if there's nothing else to send.
else
//do other stuff/return to select loop
Get rid of your while loop that sleeps
I am facing some of the same issues right now:
- If you have a small amount of connections, but with large transfers, I would just create a threadpool, and let the writes block for the writer threads.
- If you have a lot of connections then you could use full Java NIO, and register OP_WRITE on your accept()ed sockets, and then wait for the selector to come in.
The Orielly Java NIO book has all this.
Also:
http://www.exampledepot.com/egs/java.nio/NbServer.html?l=rel
Some research online has led me to believe NIO is pretty overkill unless you have a lot of incoming connections. Otherwise, if its just a few large transfers - then just use a write thread. It will probably have quicker response. A number of people have issues with NIO not repsonding as quick as they want. Since your write thread is on its own blocking it wont hurt you.