I'm working on a MUD in java. I read player input every tick, but I'm using Scanner which uses blocking operations. I want to have non-blocking input.
I've looked at the nio package which has a Selector class, but I'm not sure how to use it with regard to System.in. I figure I'll definitely need it once I'm running a server, but for now everything is offline.
I've tried extending the main class from Applet and overriding keyDown, but that just meant input was no longer accepted after the first one. Sure, I wasn't blocking anything anymore, but then there was no more input. keyDown never got called again, I guess.
Perhaps threads can be interrupted even when they are executing blocking operations?
Thanks for any insight into this problem.
You can't do that with the system console because by now it can't be done in a multi-platform way.
You can use swing window as console or find a JNI based approach but it might not work on some platforms.
You may use JCurses. It might work, it's based on JNI and supports Windows and Linux.
keyDown() is deprecated so I'd suggest to use processKeyEvent and a keyListener instead.
Perhaps threads can be interrupted even when they are executing blocking operations?
Yes if you have a reference to the thread object you want to interrupt, you can simply call interrupt() method on that instance. And in the run method of the thread you can handle the interrupted exception. However, this seems a little bit hack-ish. I don't see how this is more helpful than using a simple KeyListener.
JLine might fit your bill as well:
http://jline.sourceforge.net/apidocs/src-html/jline/ConsoleReader.html#line.1447
I had had to solve similar problem with blocking writing/reading from http. In that particular case I used local buffer and Threads.
Idea is simple, one Thread read from stdin and put content in buffer. Second do same with writing.
And then you use nonblocking queries into your buffer.
Sample code:
class NonBlockingReader implements Runnable{
Reader in;
List buffer;
public void run(){
String line=null;
while((line=in.readLine())!=null){
storeLine(line);
}
}
private synchronized storeLine(String line){
buffer.add(line);
}
public synchronized String getLine(){
if(list.size()>0)
return list.removeFirst();
return null;
}
}
// .. same for writer, then you jast pass stdin and stdout ...
Related
Is there a way to immediately print the message received from the client without using an infinite loop to check whether the input stream is empty or not?
Because I found that using infinite loop consumes a lot of system resources, which makes the program running so slow. And we also have to do the same (infinite loop) on the client side to print the message on the screen in real time.
I'm using Java.
You should be dealing with the input stream in a separate Thread - and let it block waiting for input. It will not use any resources while it blocks. If you're seeing excessive resource usage while doing this sort of thing, you're doing it wrong.
I think you can just put your loop in a different thread and have it sleep a bit (maybe for half a second?) between iterations. It would still be an infinite loop, but it would not consume nearly as many resources.
You don't you change your architecture a little bit to accommodate WebSockets. check out Socket.IO . It is a cross browser WebSockets enabler.
You will have to write controllers (servlets for example in java) that push data to the client. This does not follow the request-response architecture.
You can also architect it so that a "push servlet" triggers a "request" from the client to obtain the "response".
Since your question talks about Java, and if you are interested in WebSockets, check this link out.
If you're using Sockets, which you should be for any networking.
Then you can use the socket's DataInputStream which you can get using socket.getInputStream() (i think that's the right method) and do the following:
public DataInputStream streamIn;
public Socket soc;
// initialize socket, etc...
streamIn = soc.getInputStream();
public String getInput() {
return (String) streamIn.readUTF(); // Do some other casting if this doesn't work
}
streamIn.readUTF() blocks until data is available, meaning you don't have to loop, and threading will let you do other processing while you wait for data.
Look here for more information on DataInputStream and what you can do with it: http://docs.oracle.com/javase/6/docs/api/java/io/DataInputStream.html
A method that does not require threads would involve subclassing the input stream and adding a notify type method. When called this method would alert any interested objects (i.e. objects that would have to change state due to the additions to the stream) that changes have been made. These interested objects could then respond in anyway that is desired.
Objects writing to the buffer would do their normal writing, and afterward would call the notify() method on the input stream, informing all interested objects of the change.
Edit: This might require subclassing more than a couple of classes and so could involve a lot of code changes. Without knowing more about your design you would have to decide if the implementation is worth the effort.
There are two approaches that avoid busy loops / sleeps.
Use a thread for each client connection, and simply have each thread call read. This blocks the thread until the client sends some data, but that's no problem because it doesn't block the threads handling other clients.
Use Java NIO channel selectors. These allow a thread to wait until one of set of channels (in this case sockets) has data to be read. There is a section of the Oracle Java Tutorials on this.
Of these two approaches, the second one is most efficient in terms of overall resource usage. (The thread-per-client approach uses a lot of memory on thread stacks, and CPU on thread switching overheads.)
Busy loops that repeatedly call (say) InputStream.available() to see if there is any input are horribly inefficient. You can make them less inefficient by slowing down the polling with Thread.sleep(...) calls, but this has the side effect of making the service less responsive. For instance, if you add a 1 second sleep between each set of polls, the effect that each client will see is that the server typically delays 1 second before processing each request. Assuming that those requests are keystrokes and the responses echo them, the net result is a horribly laggy service.
I have a Java process that runs in the background. How can I quickly signal the process to show its window? I want a really light-weight script that can do this and can be launched from the Start Menu.
I think maybe a BAT file that checks if the lock file has been touched in the last few seconds, signal the process, otherwise, create a new one. The signal could be by creating another file that the process would be listening for.
That works, but it seems inefficient. Hesitation sounds unavoidable.
I could use Java instead of a BAT file, still that leaves the question of how to signal the background process. This only has to work in Windows, but I am good with Java so that is what I am using.
Any ideas?
One option would be to have that process having a listener on a port (as an example 8888), then you could send a message to that port (or do something like telnet localhost 8888). The running processes could have a separate thread listening on that port.
Another option would be to use JMX communication with the JVM - see http://download.oracle.com/javase/6/docs/technotes/guides/management/agent.html
Is there anything preventing you from checking the lock file from your Java process? You could use the Observer pattern to alert the main thread (or which ever thread) to changes in the file.
For example:
public class FileWatcher implements Observable {
private long lastModified;
private final File file;
public FileWatcher(File f) {
this.file = f;
this.lastModified = file.lastModified();
Thread t = new Thread() {
public void run() {
while(!stopThread) {
if(lastModified < file.lastModified()) {
lastModified = file.lastModified();
setChanged();
notifyObservers();
}
Thread.currentThread().sleep(5);
}
}
};
t.start();
}
}
DISCLAIMER: not tested or verified at all, but I'm sure you get the idea.
EDIT: oops, forgot the loop.
EDIT: new idea.
I have another idea. (I know you already accepted an answer, but I wanted to throw this out there.) Would it be possible to use the select function? In my very limited skim of the MSDN docs, this is only mentioned this in the context of sockets. I know the Linux equivalent is applicable to any file descriptor.
Instead of simply polling the file in the thread I mentioned above, let the OS do it! Pass the file into the writefds set to select and then it'll return when the file is modified. This means your process isn't spending valuable CPU time waiting for changes to the file.
I haven't verified whether or not Java exposes this call in the JDK, so it might require writing a JNI interface to get it to work. My knowledge in this area is a little fuzzy, sorry.
EDIT again again:
Found it! Java's Selector class looks like it implements select. Unfortunately, FileChannel isn't selectable, which is probably required in this case. :(
In my application which runs user submitted code[1] in separate threads, there might be some cases where the code might take very long to run or it might even have an infinite loop! In that case how do I stop that particular thread?
I'm not in control of the user code, so I cannot check for Thread.interrupted() from the inside. Nor can I use Thread.stop() carelessly. I also cannot put those code in separate processes.
So, is there anyway to handle this situation?
[1] I'm using JRuby, and the user code is in ruby.
With the constraints you've provided:
User submitted code you have no control over.
Cannot force checks for Thread.interrupted().
Cannot use Thread.stop().
Cannot put the user code in a process jail.
The answer to your question is "no, there is no way of handling this situation". You've pretty much systematically designed things so that you have zero control over untrusted third-party code. This is ... a suboptimal design.
If you want to be able to handle anything, you're going to have to relax one (or preferably more!) of the above constraints.
Edited to add:
There might be a way around this for you without forcing your clients to change code if that is a(nother) constraint. Launch the Ruby code in another process and use some form of IPC mechanism to do interaction with your main code base. To avoid forcing the Ruby code to suddenly have to be coded to use explicit IPC, drop in a set of proxy objects for your API that do the IPC behind the scenes which themselves call proxy objects in your own server. That way your client code is given the illusion of working inside your server while you jail that code in its own process (which you can ultimately kill -9 as the ultimate sanction should it come to that).
Later you're going to want to wean your clients from the illusion since IPC and native calls are very different and hiding that behind a proxy can be evil, but it's a stopgap you can use while you deprecate APIs and move your clients over to the new APIs.
I'm not sure about the Ruby angle (or of the threading angle) of things here, but if you're running user-submitted code, you had best run it in a separate process rather than in a separate thread of the same process.
Rule number one: Never trust user input. Much less if the input is code!
Cheers
Usually you have a variable to indicate to stop a thread. Some other thread then would set this variable to true. Finally you periodically check, whether the variable is set or not.
But given that you can't change user code , I am afraid there isn't a safe way of doing it.
For Running Thread Thread.Interrupt wont actually stop as sfussenegger mentioned aforth (thanks sfussenegger recollected after reading spec).
using a shared variable to signal that it should stop what it is doing. The thread should check the variable periodically,(ex : use a while loop ) and exit in an orderly manner.
private boolean isExit= false;
public void beforeExit() {
isExit= true;
}
public void run() {
while (!isExit) {
}
}
I need to have a buffered char stream, into which I write in one thread and from which I read in another thread. Right now I'm using PipedReader and PipedWriter for it, but those classes cause a performance problem: PipedReader does a wait(1000) when its internal buffer is empty, which causes my application to lag visibly.
Would there be some library which does the same thing as PipedReader/PipedWriter, but with better performance? Or will I have to implement my own wheels?
The problem was that when something is written to the PipedWriter, it does not automatically notify the PipedReader that there is some data to read. When one tries to read PipedReader and the buffer is empty, the PipedReader will loop and wait using a wait(1000) call until the buffer has some data.
The solution is to call PipedWriter.flush() always after writing something to the pipe. All that the flush does is call notifyAll() on the reader. The fix to the code in question looks like this.
(To me the PipedReader/PipedWriter implementation looks very much like a case of premature optimization - why not to notifyAll on every write? Also the readers wait in an active loop, waking up every second, instead of waking only when there is something to read. The code also contains some todo comments, that the reader/writer thread detection which it does is not sophisticated enough.)
This same problem appears to be also in PipedOutputStream. In my current project calling flush() manually is not possible (can't modify Commons IO's IOUtils.copy()), so I fixed it by creating low-latency wrappers for the pipe classes. They work much better than the original classes. :-)
It should be fairly easy to wrap a char stream API around BlockingQueue.
I must say, however, it seems quite perverse that PipedReader would use polling to wait for data. Is this documented somewhere, or did you discover it for yourself somehow?
#Esko Luontola, I've been reading through your code in the sbt package to try to understand what you are doing. It seems like you want to start up a Process and pass input to it, and have the result of the action be teed to different places. Is this at all correct?
I would try modifying the main loop in ReaderToWriterCopier so that instead of doing a read() - a blocking operation that apparently when a PipedReader is involved causes polling - you explicitly wait for the Writer to flush. The documentation is clear that flush causes any Readers to be notified.
I'm not sure how to run your code so I can't get deeper into it. Hope this helps.
I implemented something a little similar, and asked a question whether anyone else had any better thought out and tested code.
I've just started messing around with JLine to parse character input in console mode. It seems to work well, but I'm wondering:
Is there a nonblocking way in JLine to find out if characters are available? (i.e. like kbhit() in Windows.)
I suppose I could always wrap keyboard input in its own thread which then offers the keyboard characters in a thread-safe queue to the main thread, but that seems like it should be unnecessary.
EDIT: This is character-by-character parsing. I am not going to use a GUI. The usual InputStream I/O in Java in console mode requires you to hit the Enter key first (e.g. it's buffered input only). Please don't tell me character-by-character input in console mode is impossible in Java; it isn't. JLine does it using a portable interface with a platform-dependent implementation.
Edit update: I was able to hack together a helper class to do the blocking I/O in a worker thread (using JLine for the per-character I/O, warning: you have to parse Ctrl-C yourself!) & then communicate via a synchronized queue with an isempty() routine. For what I'm doing right now that's fine, but I would really like to know a Good Way To Do This In The Future.
You seem to be on the right track.
I think the "right" way to do this is a worker thread that pours all the blocking I/O into a non-blocking queue. Hava a look at ConcurrentLinkedQueue from java.util.concurrent.
You can't use a console to get non-blocking input without native libraries.
You'll have to write a Swing app and write a KeyListener
Read this tutorial:
http://java.sun.com/docs/books/tutorial/uiswing/events/keylistener.html