I am just trying to control processbuilder inputstream and outputstream from different class
It is main class
public class Controller
{
public static void main(String[]args)
{
Runner r=new Runner("Test");
r.activateInput();
r.setInput("Test");
}
}
It is other class to run process
import java.io.*;
public class Runner
{
boolean activeInput=true;
boolean active=true;
String input;
public Runner(String command)
{
try {
// create a new process
System.out.println("Creating Process...");
ProcessBuilder compile = new ProcessBuilder("java","TestOut");
compile.directory(new File("C:/Users/abhishek221192/Documents/Socket"));
Process process = compile.start();
OutputStream stdin = process.getOutputStream ();
InputStream stderr = process.getErrorStream ();
InputStream stdout = process.getInputStream ();
final BufferedReader reader = new BufferedReader (new InputStreamReader(stdout));
BufferedReader error = new BufferedReader (new InputStreamReader(stderr));
final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin));
//final Scanner scan=new Scanner(System.in);
Thread T=new Thread(new Runnable() {
#Override
public void run() {
while(active)
{
if(activeInput)
System.out.println(activeInput+" "+input);
String data ="Abhi";
data += "\n";
try {
if(activeInput){
writer.write(data);
writer.flush();
activeInput=false;
}
//
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
} );
T.start();
T.setName("Input");
Thread T1=new Thread(new Runnable() {
#Override
public void run() {
String line;
try{
while ((line = reader.readLine ()) != null) {
System.out.println(line);
}} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} );
T1.start();
T1.setName("Output");
/*
String line;
while ((line = error.readLine ()) != null) {
System.out.println(line);
}
*/
//stdout.close();
//error.close();
//T.stop();
//stdin.close();
//System.err.println("stdin closed");
active=false;
// close the output stream
System.out.println("Closing the output stream...");
//testProcessBuilder();
} catch (Exception ex) {
System.out.println("Error"+ex.getMessage());
}
}
public void activateInput()
{
this.activeInput=true;
System.out.println("active"+activeInput);
}
public void setInput(String input)
{
this.input=input;
}
}
It is TestOut code it include only one input statement
TestOut.java
import java.util.*;
public class TestOut
{
public static void main(String[]args)
{
Scanner sc=new Scanner(System.in);
System.out.println("Output hello TestOut");
System.out.println("Output1 "+sc.nextLine());
}
}
I am geting this output
Creating Process...
true null
Closing the output stream...
activetrue
Output hello TestOut
Output1 Abhi
r.setInput(); is not setting value
Couple of changes i made to make it work. the main problem with this piece of code is concurrency issues as two threads are working on same set of data. activeInput is being modified by Controller and by thread T
Change 1:
public synchronized void activateInput(boolean activate) {
this.activeInput = activate;
System.out.println("active" + activeInput);
}
if (activeInput) {
writer.write(data);
writer.flush();
activateInput(false);
}
declared method activateInput synchronized and replaced activateInput = false with the method call in thread T
Change 2:
// active = false;
commented out this line at the end of Runner() method because it is stopping the writer Thread unnecessarily.
Change 3:
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Added this at the end of Writer Thread's while loop to give writer Thread T some breathing space and to give it a chance on reading the values.
Output:
Here is the output i got:
Creating Process...
activetrue
Output hello TestOut
true Test
activefalse
Output1 Abhi
Hope this helps.
Related
here is code
private static class NgrokRunner implements Runnable {
private InputStream inputStream;
private boolean doStop = false;
public NgrokRunner(InputStream inputStream) {
this.inputStream = inputStream;
}
#Override
public void run() {
// TODO Auto-generated method stub
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
try {
while((line = reader.readLine()) != null) {
System.out.println(line);
if (keepRunning()) {
continue;
} else {
System.out.println("break ----");
break;
}
}
} catch (Exception e) {
//TODO: handle exception
System.out.println("Ngrok exception");
}
}
public synchronized void doStop() {
this.doStop = true;
}
private synchronized boolean keepRunning() {
return this.doStop == false;
}
}
and i started above thread like this
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command("ngrok", "http","8080", "--log=stdout");
try {
Process process = processBuilder.start();
NgrokRunner runner = new NgrokRunner(process.getInputStream());
Thread ngrokThread = new Thread(runner);
ngrokThread.start();
for (int i = 0; i < 4; i++) {
System.out.println(i);
Thread.sleep(10L * 100L);
}
//System.out.println("It works");
runner.doStop();
} catch (Exception e) {
//TODO: handle exception System.out.println(e);
}
But in while loop my child thread which is reading input from ngrok , blocking and even after calling doStop() it never reached at if condition where i am checking bool flag to exit from thread.
Well can anyone suggest me logic to achieve my ideal situation.
what i want is "Run ngrok server through binary file of ngrok in a thread and close the thread/ngrok whenever i want ( like when user wants through a pause/end button )"
ok so i solved it and here is final solution
run() code :
#Override
public void run() {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
try {
while(!Thread.interrupted()) {
if (!reader.ready()) {
try {
Thread.sleep(1000);
continue;
} catch (InterruptedException e) {
//TODO: handle exception
System.out.println("We got interrupted");
return;
}
}
line = reader.readLine();
System.out.println(line);
}
} catch (IOException e) {
//TODO: handle exception
System.out.println("Ngrok exception" + e);
}
}
Now from main thread
try {
process = processBuilder.start();
NgrokRunner runner = new NgrokRunner(process.getInputStream());
ngrokThread = new Thread(runner);
ngrokThread.start();
for (int i = 0; i < 8; i++) {
System.out.println(i);
Thread.sleep(1000);
}
ngrokThread.interrupt();
} catch (Exception e) {
//TODO: handle exception
System.out.println(e);
}
I have created two threads and modified the run function so that one thread reads one line and the other writes the same line to the new file. This happens till the whole file is copied. The problem i am getting is that even though i have used variables to control that the threads execute one by one but still the threads are executing unevenly i.e one thread executes multiple times and then the control transfers. Any solutions i have attached the code. I am new to java as it is only for class assignment so the code might not be the most optimized.
public class thread1 extends Thread {
//To create producer and consumer as threads
//Shared variable
public static int x = 0;//checks if all lines are read
public static String line; /holds lines from file
public static int j = 0;//variable to switch between threads based upon its value
public thread1(String threadName) { //Constuctor
super(threadName); //Call to constructor of Thread class
}
public void run() {
while (x != -1)
{
if (Thread.currentThread().getName().contains("Reader")) {
if (x != -1&&j==0)
{
j=1;
String fileName = "d:/salfar.txt";
try {
// FileReader reads text files in the default encoding.
FileReader fileReader =
new FileReader(fileName);
// Always wrap FileReader in BufferedReader.
BufferedReader bufferedReader =
new BufferedReader(fileReader);
for (int check = 0; check <= x; check++) {
line = bufferedReader.readLine();
}
if (line == null) {
x = -1;
} else {
System.out.println(line);
x++;
}
// Always close files.
bufferedReader.close();
} catch (FileNotFoundException ex) {
System.out.println(
"Unable to open file '"
+ fileName + "'");
} catch (IOException ex) {
System.out.println(
"Error reading file '"
+ fileName + "'");
// Or we could just do this:
// ex.printStackTrace();
}
}
yield();
}
else if (Thread.currentThread().getName().contains("writer")) {
if (x != -1 && line != null&&j==1)
{
j=0;
String fileName = "d:/salfar1.txt";
try {
// Assume default encoding.
FileWriter fileWriter =
new FileWriter(fileName, true);
// Always wrap FileWriter in BufferedWriter.
BufferedWriter bufferedWriter =
new BufferedWriter(fileWriter);
// Note that write() does not automatically
// append a newline character.
bufferedWriter.write(line);
bufferedWriter.newLine();
System.out.println("y");
// Always close files.
bufferedWriter.close();
} catch (IOException ex) {
System.out.println(
"Error writing to file '"
+ fileName + "'");
// Or we could just do this:
// ex.printStackTrace();
}
}
Thread.yield();
}
else{}
}
}
public static void main(String[] args) {
thread1 p = new thread1("Reader");
thread1 c = new thread1("writer");
p.start();
c.start();
}
}
Thanks
You cannot control the order of thread execution. However, to perform read and write operation via separate threads, you should use BlockingQueue which has the following properties:
A Queue that additionally supports operations that wait for the queue to become non-empty when retrieving an element, and wait for space to become available in the queue when storing an element.
ReaderThread will read from the input file.
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.concurrent.BlockingQueue;
public class ReaderThread implements Runnable{
protected BlockingQueue<String> blockingQueue = null;
public ReaderThread(BlockingQueue<String> blockingQueue){
this.blockingQueue = blockingQueue;
}
#Override
public void run() {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(new File("./inputFile.txt")));
String buffer =null;
while((buffer=br.readLine())!=null){
blockingQueue.put(buffer);
}
blockingQueue.put("EOF"); //When end of file has been reached
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch(InterruptedException e){
}finally{
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
WriterThread will write to output file.
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.concurrent.BlockingQueue;
public class WriterThread implements Runnable{
protected BlockingQueue<String> blockingQueue = null;
public WriterThread(BlockingQueue<String> blockingQueue){
this.blockingQueue = blockingQueue;
}
#Override
public void run() {
PrintWriter writer = null;
try {
writer = new PrintWriter(new File("outputFile.txt"));
while(true){
String buffer = blockingQueue.take();
//Check whether end of file has been reached
if(buffer.equals("EOF")){
break;
}
writer.println(buffer);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch(InterruptedException e){
}finally{
writer.close();
}
}
}
From Launcher class start your multithreaded read and write.
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class Launcher {
public static void main(String[] args) {
BlockingQueue<String> queue = new ArrayBlockingQueue<String>(1024);
ReaderThread reader = new ReaderThread(queue);
WriterThread writer = new WriterThread(queue);
new Thread(reader).start();
new Thread(writer).start();
}
}
Here is my solutions. My idea is to use the actually file name that our threads will be reading and writing to. There is only one issue that we need to make sure of, that no two threads are trying to operate on the same file. The solution to this is to simply have a synchronized code block in your run method.
We must recall that Strings are not mutable in Java. Consider the following:
String s1 = "test.txt";
String s2 = "test.txt";
Now, we must ask our selves how does the jvm reuse the immutable "test.txt". In this case both s1 & s2 String objects point to the same "test.txt".
Understanding this concept will also do the trick for us:
public class Client {
public static void main( String args [] ) {
String filename = "test.txt";
String filename2 = "test.txt";
Reader reader = new Reader( filename ) ;
Writer writer = new Writer( filename2 ) ;
while(true) {
reader.run();
writer.run();
}
}
}
public class Writer implements Runnable {
public String filename;
public Writer( String filename ) {
this.filename = filename;
}
#Override
public void run() {
synchronized( this.filename ) {
System.out.println( "writing to a file:" + this.filename );
}
}
}
public class Reader implements Runnable {
public String filename;
public Reader( String filename ) {
this.filename = filename;
}
#Override
public void run() {
synchronized( this.filename ) {
System.out.println( "reading a file:" + this.filename );
}
}
}
I have to build a chat program.
There is the server class, the client class and two threads to write and receive messages.
the two threads should run in an infinite loop and check all the time if there is an input and print that input afterwards.
But my program works for just one round. So the server and the client can write one single message, afterwards it stops and does not check for another message. Why does the thread not start again from the begin when it's never interrupted? --> see the code beneath
I hope you know what my problem is, it's quite hard for me to describe.
Thread to read a new Message
public class MsgWriter extends Thread {
private Socket s;
public MsgWriter(Socket s){
this.s = s;
}
public void run(){
int i = 0;
OutputStream out = null;
PrintWriter writer;
Scanner input;
while(!interrupted()){
try{
synchronized(s){
input = new Scanner (System.in);
out = s.getOutputStream();
writer = new PrintWriter(out);
String toserver = input.nextLine();
writer.write(toserver);
writer.flush();
System.out.println("me: " + toserver);
}
try {
Thread.sleep((int) (100 * Math.random()));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}catch(Exception e) {
}
}
}
}
Thread to check if there is a new message and prints it.
public class MsgReader extends Thread {
Socket s;
public MsgReader(Socket s){
this.s = s;
}
public void run() {
int i = 0;
while (!interrupted()) {
try{
synchronized(s){
InputStream in = s.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String s = null;
while((s=reader.readLine()) != null){
System.out.println("d");
}
}
try {
Thread.sleep((int) (100 * 1));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}catch (Exception e){
}
}
}
}
The Server class starts a new server and waits for a client, afterwards it starts the two threads. The same with the client class, it connects to the server and starts the threads.
You're probably thowing an exception somewhere. In your catch blocks, print the error.
try {
} catch (Exception e) {
System.out.println("Error: " + e);
}
I have two threads running, userInputThread waits for user input from the command line and interrupterThread tries to interrupt userInputThread 1 sec after starting. Obviously you cannot interrupt a thread that is blocked by the System.in. Another answer suggests to close System.in with System.in.close() before interrupting a thread. But when I run the following code, the userInputThread never gets interrupted and the app just hangs without closing.
class InputInterruptionExample {
private Thread userInputThread;
private Thread interrupterThread;
InputInterruptionExample() {
this.userInputThread = new Thread(new UserInputThread());
this.interrupterThread = new Thread(new InterrupterThread());
}
void startThreads() {
this.userInputThread.start();
this.interrupterThread.start();
}
private class UserInputThread implements Runnable {
public void run() {
try {
System.out.println("enter your name: ");
String userInput = (new BufferedReader(new InputStreamReader(System.in))).readLine();
} catch (IOException e) {
System.out.println("Oops..somethign went wrong.");
System.exit(1);
}
}
}
private class InterrupterThread implements Runnable {
public void run() {
try {
sleep(1000);
System.out.println("about to interrupt UserInputThread");
System.in.close();
userInputThread.interrupt();
userInputThread.join();
System.out.println("Successfully interrupted");
} catch (InterruptedException e) {
} catch (IOException ex) {
System.out.println("Oops..somethign went wrong.");
System.exit(1);
}
}
}
public static void main(String[] args) {
InputInterruptionExample exampleApp = new InputInterruptionExample();
exampleApp.startThreads();
}
}
There's already a similar question, but there aren't any definite answers.
This has solved the problem:
class InputInterruptionExample {
private UserInputThread userInputRunnable;
private Thread userInputThread;
private Thread interrupterThread;
InputInterruptionExample() {
this.userInputRunnable = new UserInputThread();
this.userInputThread = new Thread(userInputRunnable);
this.interrupterThread = new Thread(new InterrupterThread());
}
void startThreads() {
this.userInputThread.start();
this.interrupterThread.start();
}
private class UserInputThread implements Runnable {
private InputStreamReader isr;
private BufferedReader br;
UserInputThread() {
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
}
public void run() {
try {
System.out.println("enter your name: ");
try{
String userInput = br.readLine();
} catch(NullPointerException e) {}
} catch (IOException e) {
System.out.println("Oops..somethign went wrong.");
System.exit(1);
}
}
public void closeBufferdReader() {
try {
System.in.close();
} catch (IOException e) {
System.out.println("Oops..somethign went wrong in closeBufferdReader() method");
System.exit(1);
}
}
}
private class InterrupterThread implements Runnable {
public void run() {
try {
sleep(1000);
userInputRunnable.closeBufferdReader();
userInputThread.interrupt();
userInputThread.join();
System.out.println("Successfully interrupted");
} catch (InterruptedException e) {}
}
}
public static void main(String[] args) {
InputInterruptionExample exampleApp = new InputInterruptionExample();
exampleApp.startThreads();
}
}
Update: This only works when BufferedReader is split up this way:
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
String userInput = br.readLine();
For some reason the interruption does not seem to work when the readLine() structure is written as a oneliner:
this.userInput = (new BufferedReader(new InputStreamReader(System.in))).readLine();
So while it is possible to interrupt the thread in the split-up BufferedReader structure, it is now impossible to read user's input.
If someone could show a way to be able to get user input as well as interrupt the UserInputThread when the user doesn't provide any input in time (while interrupter is sleeping), please do.
All of my research leads me to believe that the underlying .read() in the .readLine() call cannot be interrupted (Without destroying the Process that System.in is attached to, at least). The only other choices at that point is to use a polling IO scheme or switch to NIO.
Here's a quick (and very dirty/ugly) adaptation of your code into a polling IO scheme. It's not an interupt solution so it's not directly answering your question, but rather hopefully getting you the behavior you desire.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.atomic.AtomicBoolean;
public class InputInterruptionExample {
private UserInputThread uiThreadObj = null;
private Thread inputThread = null;
private Thread interrupThread = null;
public InputInterruptionExample() {
this.uiThreadObj = new UserInputThread();
this.inputThread = new Thread(this.uiThreadObj);
this.interrupThread = new Thread(new InterrupterThread());
}
void startThreads() {
this.inputThread.start();
this.interrupThread.start();
}
private class UserInputThread implements Runnable {
private final AtomicBoolean runCmd = new AtomicBoolean(true);
public void run() {
try {
final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("enter your name: ");
while (this.runCmd.get()) {
if (System.in.available() > 0) {
String userInput = br.readLine();
System.out.println("You typed: " + userInput);
System.out.println("enter your name: ");
} else {
Thread.sleep(5); //minimal sleep to prevent CPU peg
}
}
System.out.println("Finishing normally.");
} catch (IOException e) {
System.out.println("Oops..somethign went wrong.");
System.exit(1);
} catch (Exception e) {
System.out.println("What'd you do?!");
e.printStackTrace();
}
}
public final void requestStop() {
this.runCmd.set(false);
}
}
private class InterrupterThread implements Runnable {
public void run() {
try {
Thread.sleep(1000 * 10);
System.out.println("Requesting that UserInputThread stop.");
uiThreadObj.requestStop();
System.out.println("Request made.");
} catch (InterruptedException e) {
System.out.println("Oops..somethign went wrong.");
System.exit(1);
}
}
}
public static void main(String[] args) {
InputInterruptionExample exampleApp = new InputInterruptionExample();
exampleApp.startThreads();
}
}
I need to extract the input stream of the process after I start it.
Today I can get the initial information but the method doesn't return until I close the application (in this case the application started by the process: gedit and firefox). I mean, I know it just return after I close the process, but I'd like to have a workaround to get that prior to the process closing.
See my code below.
public class ProcessInvokerExtractingProcessInformation {
public static void main(String args[]) {
try {
Process pOpenApp = new ProcessBuilder(new String[] { "gedit",
"/home/thais/Documents/gedit_doc1" }).start();
printInformation("pOpenApp", pOpenApp);
// * just for testing error message and input stream
Process openFirefox = new ProcessBuilder(new String[] { "firefox" })
.start();
printInformation("lsInstruction", openFirefox);
deleteProcess(pOpenApp);
deleteProcess(openFirefox);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// method for testing information we can see regarding the process
public static void printInformation(String id, final Process process) {
System.out.println(" Process " + id + ":");
//tried to run in a separated thread but didn't work as well
Runnable r = new Runnable(){
public void run(){
System.out.print("\n Process error message -> ");
printScannedStream(process.getErrorStream());
System.out.println("\n Process input message -> ");
printScannedStream(process.getInputStream());
}
};
Thread a = new Thread(r);
a.start();
/* other approaches to print the streams, tried before
StringWriter writer = new StringWriter();
try {
PrintWriter pWriter = new PrintWriter(new
BufferedOutputStream(process.getOutputStream()));
pWriter.write("Hi"); pWriter.flush(); System.out.println(
" Process output stream is for writing so there is no information "
);
*//*
InputStreamReader isr = new InputStreamReader(
process.getErrorStream());
BufferedReader br = new BufferedReader(isr);
System.out.print("\n Process error message -> ");
while (br.readLine() != null) {
System.out.print(br.readLine());
}
System.out.println("\n Process input message -> ");
isr = new InputStreamReader(process.getInputStream());
br = new BufferedReader(isr);
while (br.readLine() != null) {
System.out.print(br.readLine());
}
br.close();
isr.close();*/
/*
* IOUtils.copy(process.getErrorStream(), writer, null);
* System.out.println(" Process error message -> " +
* writer.toString());
*
* IOUtils.copy(process.getInputStream(), writer, null);
* System.out.println(" Process input stream message -> " +
* writer.toString()+"\n");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
*/
}
/**
* Method that close all streams and after destroy the process It's
* important to close the streams to avoid file descriptions leaking
*
* #param process
*/
public static void deleteProcess(Process process) {
try {
process.getInputStream().close();
process.getOutputStream().close();
process.getErrorStream().close();
process.destroy();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void printScannedStream(java.io.InputStream is) {
try {
Scanner scanner = new Scanner(is);
while(scanner.hasNext()) {
System.out.print(scanner.next());
}
} catch (java.util.NoSuchElementException e) {
e.printStackTrace();
}
}
}
I had the same problem and I solved it with using an additional thread.
class InputHandler implements Runnable {
InputStream input_;
InputHandler(InputStream input) {
input_ = input;
}
public void run() {
try {
int c;
String line = "";
while ((c = input_.read()) != -1) {
if (((char) c == '\r') || ((char) c == '\n')) {
if (!line.isEmpty()) flushString(line);
line = "";
} else
line += (char) c;
}
} catch (Throwable t) {
t.printStackTrace();
}
}
private void flushString(String s) {
// any code to process data from stream
Logger.debug("library: " + getClass().getName() + ": compress: output: " + s);
}
}
Process process = run.exec(ffmpegCmdString);
// read output
InputHandler stderrHandler = new InputHandler(process.getErrorStream());
new Thread(stderrHandler).start();
InputHandler stdoutHandler = new InputHandler(process.getInputStream());
new Thread(stdoutHandler).start();
process.waitFor();