I have a thread that must read the stdin and the stdout from a console application. This thread must to read continually until the end of the java program (the java program starts the console application and read and write with him).
Now I have this question: the tread, when reads from console application, if reads a determined thing must to set a flag variable that runs an exception. I solved putting a latch CountDown. But when the thread doesn't read this thing, the barrier latch.await() locks the continuos of the java program and I don't know how to resolve this trouble.
This is the part of code:
p = Runtime.getRuntime().exec("testpad -i -c"+can+" -n"+pad+" "+pathFile);
final InputStream inStream = p.getInputStream();
Thread uiThread = new Thread("UIHandler") {
#Override
public void run() {
InputStreamReader reader = new InputStreamReader(inStream);
Scanner scan = new Scanner(reader);
String prec=null;
while (scan.hasNextLine()) {
prec=scan.nextLine();
System.out.println(prec);
if(err.equals(prec)){
flag[0] = 1;
latch.countDown();
}
}
}
};
uiThread.start();
latch.await();
if(flag[0]!=1){
this.dispose();
new menu().setVisible(true);
}
else{
Exception e = new Exception("Error!");
Component f = null;
JOptionPane.showMessageDialog(f, err, e.getMessage(), JOptionPane.WARNING_MESSAGE);
this.dispose();
new inizio().setVisible(true);
}
In the if in the thread there is the part that sets the flag variable. But if the thread doesn't enter there, the java program blocks for the barriel latch.await(). Is there a method to do this thing and never blocks the program? Thanks at all.
latch.await() will block until the latch finishes so you should move that line to the end.
Related
I have a question how to implement a variation of whats found here:
Set Time Limit on User Input (Scanner) Java
In my case, I would like to ignore the input if the Timelimit is reached while keeping the program alive.
String str = "";
TimerTask task = new TimerTask(){
public void run(){
if(str.equals("")){
System.out.println("No Valid Input detected");
//TimerTask should end here along with the Input
//Other example has System.exit which will also terminate the
//entire program
}else {
// still keep the program alive. The condition itself isn't
//important.
}
}
Timer timer = new Timer();
timer.schedule(task, 10*1000);
Scanner scanner = new Scanner(System.in);
do{
System.out.println("Type a message");
str = scanner.nextLine();
}while(!str.equals("hello"));
timer.cancel();
REACHED HERE!
If the input is given within 10 seconds(and it's valid), the loop ends and the task is canceled, which is perfect. However, if the input is not valid and the timer ends, I would like for it to stop asking for input and skip to the "REACHED HERE" position. Is that even possible?
As #Sedrick mentions, the simplest solution to this is a second thread. The problem is that reading from System.in is blocking. Clearly the example you linked to solves that problem with a System.exit(), but that's too extreme for your case.
Another spin on it might be to use a Deque (double-ended queue) to relay the input, with the timeout on there:
BlockingDeque<String> deque = new LinkedBlockingDeque<>();
new Thread(() -> {
Scanner scanner = new Scanner(System.in);
String input;
do {
System.out.println("Type a message");
input = scanner.nextLine();
deque.add(input);
} while (!input.equals("hello"));
}).start();
String str;
do {
str = deque.poll(10, TimeUnit.SECONDS);
} while (str != null && !str.equals("hello"));
System.out.println("REACHED HERE!");
Expanded answer...
The idea above was to only create the thread once, and re-use the deque as the proxy for System.in. But, in the thread, the read from System.in will always be blocking - there's no clean way to interrupt the thread, short of System.exit().
This can be refined a bit though. Firstly, if the thread is marked as a daemon thread, this allows the JVM to shutdown around it still. E.g. if the main() method completes, the JVM will exit cleanly too:
Thread thread = new Thread(() -> {
...
});
thread.setDaemon(true);
thread.start();
However, by using InputStream.available(), it is possible to poll for waiting input. This then makes it possible to interrupt the thread cleanly:
BlockingDeque<String> deque = new LinkedBlockingDeque<>();
Thread thread = new Thread(() -> {
Scanner scanner = new Scanner(System.in);
String input;
try {
do {
if (System.in.available() > 0) {
input = scanner.nextLine();
deque.add(input);
} else
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
System.err.println("Thread stopped");
break;
}
} while (true);
} catch (IOException ex) {
ex.printStackTrace();
}
});
thread.start();
System.out.println("Type a message");
String str;
do {
str = deque.poll(10, TimeUnit.SECONDS);
} while (str != null && !str.equals("hello"));
System.out.println("REACHED HERE!");
thread.interrupt();
It looks like there's some risk with the user typing a few letters without a line feed. At the moment that would still hang, but this didn't happen on Windows - apparently data from the command window is only released to System.in line by line.
I am writing a server in Java, which is multithreaded. I have three main active threads that I build and start from my main method:
public class Run{
public static void main(String[] args){
try{
/*
* Definition and initialization of "server," "time," and
* "commands" variables not shown.
*/
new Thread(server).start();
new Thread(time).start();
new Thread(commands).start();
}catch(FileNotFoundException unfound){
/* Exception code not shown */
}catch(IOException ioe){
/* Exception code not shown */
}
}
}
My commands thread is used, for example, for stopping the server by have the input "q" into the console window. commands's run method is defined as so:
public void run(){
while(server.running.get()){
try{
String next = scan.nextLine();
if(next.equalsIgnoreCase("q")){
server.shutdown();
close();
}else
System.out.println(LocalDateTime.now() + " - Unknown command.");
}catch(IOException ioe){
System.out.println(LocalDateTime.now() + " - The commands thread has produced an exception.");
}
}
}
*Where scan is defined as: Scanner scan = new Scanner(System.in);
When I run my server all my threads work, except the commands thread as the console is not accepting inputs.
I then realized, if I waited for my server thread (this is the thread I most care about) to join up with my main (static method) thread, my commands thread then worked. Meaning the console accepted inputs if I changed my main method code to this:
Thread t1 = new Thread(server);
t1.start();
new Thread(time).start();
new Thread(commands).start();
try{
t1.join();
}catch(Exception e){
e.printStackTrace();
}
Now to my question. Why does console input only work if the main thread is still active? I honestly do not need my main thread anymore, so letting it terminate would be just fine.
Is there something I am doing incorrectly here with just defining my threads without a name? I am able to terminate each thread nicely as they are interweaved with each other and everything works just except my commands thread.
EDIT:
I really appreciate all of the answers regarding a fix to this issue but what I am really after is the reason of why this is happening.
The server thread spirals off and does it own thing (i.e. constantly looking for new connections and establishing new environments for those connections) and the renewal thread goes off and does its own thing as well (i.e. this is used for renewing my quota count as I am using a google API). Other than that, the above code gets the point across on what I am doing.
You should have your commands thread be your main thread.
Just put this in main() after everything else is started:
commands.run();
I don't see any problem with reading from another thread while main is gone away:
public class IOWithoutMain {
public static void main(String[] args) {
RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
System.out.printf("%s %s %s (%s)%n",
runtime.getVmVendor(),
runtime.getVmName(),
System.getProperty("java.version"),
runtime.getVmVersion());
new Thread() {
public void run() {
try {
sleep(10_000);
System.out.print("Enter input: ");
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
System.out.println(br.readLine());
} catch (InterruptedException|IOException e) {
e.printStackTrace();
}
}
}.start();
}
}
Console :
Oracle Corporation Java HotSpot(TM) 64-Bit Server VM 1.8.0_60 (25.60-b23)
Enter input: Test
Test
JVM takes care about main thread and IO streams. You can try to keep input stream intact by saving/hiding its actual value in the main thread (usual tests approach):
InputStream consoleInput = System.in;
System.setIn(new ByteArrayInputStream(new byte[0]));
If you want the main thread to terminate without terminating the JVM (and so your other threads) you can use the daemon threads.
Have a look at this link: What is Daemon thread in Java?
PS: remember that having threads which don't terminate can be dangerous especially when they use resources.
I'm writing a program that needs to read lines from a very large file (400K+ lines) and send the data in each line on to a web service. I decided to try threading and am seeing some behavior I did not expect, it appears like my BufferedReader starts reusing lines it's already given me when I call readline() on it.
My program is made up of two classes. A "Main" class that kicks off the threads and holds a static reference to the BufferedReader and has a static sychronized "readNextLine()" method that the threads can use to basically call readLine() on the BufferedReder. And the "Runnable" class that calls readNextLine() and makes a webservice call with the data from each readNextLine() call. I made the BufferedReader and readNextLine() static just because that's the only way I could think of for the threads to share the reader aside from passing an instance of my main class into the threads, I wasn't sure which was better.
After about 5 minutes, I start seeing errors in my web service saying that it's processing a line it's already processed. I'm able to verify lines are indeed being sent multiple times, minutes apart.
Does anyone have any ideas as to why the BufferedReader seems to be giving the threads lines it already read? I was under the impression readline() was sequential and all I needed to do was make sure the calls to readline() were synchronized.
I'll show some of the Main class code below. The runnable is essentially a while loop that calls readNextLine() and processes each line until there are no more lines left.
Main class:
//showing reader and thread creation
inputStream = sftp.get(path to file);
reader = new BufferedReader(new InputStreamReader(inputStream));
ExecutorService executor = Executors.newFixedThreadPool(threads);
Collection<Future> futures = new ArrayList<Future>();
for(int i=0;i<threads;i++){
MyRunnable runnable = new MyRunnable(i);
futures.add(executor.submit(runnable));
}
LOGGER.debug("futures.get()");
for(Future f:futures){
f.get(); //use to wait until all threads are done
}
public synchronized static String readNextLine(){
String results = null;
try{
if(reader!=null){
results = reader.readLine();
}
}catch(Exception e){
LOGGER.error("Error reading from file");
}
return results;
}
I'm testing what you said, but I found you get an error logic in your readNextLine() method, how can reader.readLine() be invoked as the results is null and the if condition is it is not null?
Now I finished my demo, and it seems it works well, the following is the demo, no re-read line happened:
static BufferedReader reader;
public static void main(String[] args) throws FileNotFoundException, ExecutionException, InterruptedException {
reader = new BufferedReader(new FileReader("test.txt"));
ExecutorService service = Executors.newFixedThreadPool(3);
List<Future> results = new ArrayList<Future>();
for (int i = 0; i < 3; i++) {
results.add(service.submit(new Runnable() {
#Override
public void run() {
try {
String line = null;
while ((line = readNextLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
}));
}
}
public synchronized static String readNextLine() throws IOException {
return reader.readLine();
}
Write end dead exception occurs in the following situation:
Two threads:
A: PipedOutputStream put = new PipedOutputStream();
String msg = "MESSAGE";
output.wirte(msg.getBytes());
output.flush();
B: PipedInputStream get = new PipedOutputStream(A.put);
byte[] get_msg = new byte[1024];
get.read(get_msg);
Here is the situation: A and B run concurrently, and A writes to the pipe and B reads it. B just read from the pipe and buffer of this pipe is cleared. Then A doesn't write msg to the pipe in unknown interval. However, at one moment, B read the pipe again and java.io.IOException: write end dead occurs, because the buffer of the pipe is still empty. And I don't want to sleep() thread B to wait for A writing the pipe, which is also unstable. How to avoid this problem and solve it? Thanks
"Write end dead" exceptions will arise when you have:
A PipedInputStream connected to a PipedOutputStream and
The ends of these pipe are read/written by two different threads
The threads finish without closing their side of the pipe.
To resolve this exception, simply close your Piped Stream in your Thread's runnable after you have completed writing and reading bytes to/from the pipe stream.
Here is some sample code:
final PipedOutputStream output = new PipedOutputStream();
final PipedInputStream input = new PipedInputStream(output);
Thread thread1 = new Thread(new Runnable() {
#Override
public void run() {
try {
output.write("Hello Piped Streams!! Used for Inter Thread Communication".getBytes());
output.close();
} catch(IOException io) {
io.printStackTrace();
}
}
});
Thread thread2 = new Thread(new Runnable() {
#Override
public void run() {
try {
int data;
while((data = input.read()) != -1) {
System.out.println(data + " ===> " + (char)data);
}
input.close();
} catch(IOException io) {
io.printStackTrace();
}
}
});
thread1.start();
thread2.start();
Complete code is here: https://github.com/prabhash1785/Java/blob/master/JavaCodeSnippets/src/com/prabhash/java/io/PipedStreams.java
For more details, please have a look at this nice blog: https://techtavern.wordpress.com/2008/07/16/whats-this-ioexception-write-end-dead/
you need to close PipedOutputStream, before writing thread is finished (and ofcourse after all data is written). PipedInputStream throws this exception on read() when there is no writing thread and writer is not properly closed
I want to launch a process from Java, read its output, and get its return code. But while it's executing, I want to be able to cancel it. I start out by launching the process:
ProcessBuilder pb = new ProcessBuilder(args);
pb.redirectErrorStream(true);
Process proc = pb.start();
If I call proc.waitFor(), I can't do anything until the process exits. So I'm assuming I need to something like this:
while (true) {
see if process has exited
capture some output from the process
decide if I want to cancel it, and if so, cancel it
sleep for a while
}
Is this right? Can someone give me an example of how to do this in Java?
Here's an example of what I think you want to do:
ProcessBuilder pb = new ProcessBuilder(args);
pb.redirectErrorStream(true);
Process proc = pb.start();
InputStream is = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
int exit = -1;
while ((line = br.readLine()) != null) {
// Outputs your process execution
System.out.println(line);
try {
exit = proc.exitValue();
if (exit == 0) {
// Process finished
}
} catch (IllegalThreadStateException t) {
// The process has not yet finished.
// Should we stop it?
if (processMustStop())
// processMustStop can return true
// after time out, for example.
proc.destroy();
}
}
You can improve it :-) I don't have a real environment to test it now, but you can find some more information here.
I recommend checking out Apache Commons Exec to avoid recreating the wheel. It has some nice features like choosing between synchronous vs. asynchronous execution, as well as a standard solution to spawning a watchdog process that can help in timing out the execution in case it gets stuck.
A helper class like this would do the trick:
public class ProcessWatcher implements Runnable {
private Process p;
private volatile boolean finished = false;
public ProcessWatcher(Process p) {
this.p = p;
new Thread(this).start();
}
public boolean isFinished() {
return finished;
}
public void run() {
try {
p.waitFor();
} catch (Exception e) {}
finished = true;
}
}
You would then implement your loop exactly as you describe:
Process p = Runtime.getRuntime().exec("whatever command");
ProcessWatcher pw = new ProcessWatcher(p);
InputStream output = p.getInputStream();
while(!pw.isFinished()) {
processOutput(output);
if(shouldCancel()) p.destroy();
Thread.sleep(500);
}
Depending upon what conditions would make you want to destroy the process, you might want to do that in a separate thread. Otherwise, you may block while waiting for more program output to process and never really get the option to destroy it.
EDIT: McDowell is 100% right in his comment below, so I've made the finished variable volatile.
How about this (see how it works in jcabi-heroku-maven-plugin):
/**
* Wait for the process to stop, logging its output in parallel.
* #param process The process to wait for
* #return Stdout produced by the process
* #throws InterruptedException If interrupted in between
*/
private String waitFor(final Process process) throws InterruptedException {
final BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream())
);
final CountDownLatch done = new CountDownLatch(1);
final StringBuffer stdout = new StringBuffer();
new Thread(
new VerboseRunnable(
new Callable<Void>() {
#Override
public Void call() throws Exception {
while (true) {
final String line = reader.readLine();
if (line == null) {
break;
}
System.out.println(">> " + line);
stdout.append(line);
}
done.countDown();
return null;
}
},
false
)
).start();
try {
process.waitFor();
} finally {
done.await();
IOUtils.closeQuietly(reader);
}
return stdout.toString();
}
ps. Now this implementation is available as com.jcabi.log.VerboseProcess class from jcabi-log artifact.
What would make you decide to kill the process -- an asynchronous event (such as input from the user), or a synchronous event (e.g., the process has done what you wanted it to do)? I'm guessing it's the former -- input from the user makes you decide to cancel the subprocess.
Also, how much output do you expect the subprocess to produce? If it's a lot, then the subprocess may block if you don't read from its output stream quickly enough.
Your situation may vary, but it seems that you're likely going to need at least two different threads -- one to decide whether to cancel the process, and one that handles the output from the subprocess.
Have a look here for a bit more detail: http://java.sun.com/developer/JDCTechTips/2005/tt0727.html#2