when I tried to get console input from both main thread and thread I created, the console input can only be retrieved by one thread, either main thread or new thread. code as follow:
public static void main(String[] args)
{
try
{
//start a new thread to accept user input
Thread thread = new Thread(new Runnable()
{
#Override
public void run()
{
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
try
{
while(true)
{
String input = stdIn.readLine();
System.out.println(Thread.currentThread().getName() + ":" + input);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}, "Owen");
thread.start();
//accept user input in main thread
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
while(true)
{
String input = stdIn.readLine();
System.out.println(Thread.currentThread().getName() + ":" + input);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
possible result is as follow:
always new thread:
main
Owen:main
hello
Owen:hello
what
Owen:what
how could I know current input is going to be retrieved by which thread? or Is there any way to start two consoles(or even more) for each thread?
Related
I am writing a java program that will need to run a python script.
The script will print output which will java need to read to know the progress of the script.
To be able to pause the script while running I want it to ask for input once in a while, only when java give it input the script will keep going.
Here is my Java method:
private static void sevenTry(String[] strCommands) throws IOException {
Object oLock1 = new Object();
Object oLock2 = new Object();
ProcessBuilder pBuilder = new ProcessBuilder(strCommands);
pBuilder.redirectErrorStream(true);
Process proc = pBuilder.start();
Thread tReader = new Thread() {
#Override
public void run() {
System.out.println("~~tReader starting~~");
BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
synchronized (oLock1) {
try {
String line = reader.readLine();
while (line != null && !line.trim().equals("--EOF--")) {
System.out.println("Stdout: " + line);
if (line.trim().equals("--INPUT--")) {
synchronized (oLock2) {
oLock2.notify();
}
oLock1.wait();
}
line = reader.readLine();
}
} catch (IOException e) {
System.out.println("tReader: " + e.getMessage());
} catch (InterruptedException e) {
System.out.println("tReader: " + e.getMessage());
} catch (Exception e) {
System.out.println("tReader: " + e.getMessage());
}
}
System.out.println("~~tReader end~~");
synchronized (oLock2) {
oLock2.notify();
}
}
};
Thread tWriter = new Thread() {
#Override
public void run() {
System.out.println("~~tWriter starting~~");
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
String line, input;
Scanner scan = new Scanner(System.in);
synchronized (oLock2) {
try {
oLock2.wait();
} catch (InterruptedException e1) {
System.out.println("tWriter: " + e1.getMessage());
}
}
while (tReader.isAlive()) {
synchronized (oLock1) {
System.out.println("Java: insert input");
scan.hasNext();
input = scan.nextLine();
try {
writer.write(input + "\n");
writer.flush();
} catch (IOException e) {
System.out.println("tWriter: " + e.getMessage());
}
oLock1.notify();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
System.out.println("tWriter: " + e1.getMessage());
}
}
System.out.println("~~tWriter end~~");
}
};
tReader.start();
tWriter.start();
System.out.println("~~everything submitted~~");
try {
tReader.join();
tWriter.join();
System.out.println("~~finish~~");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
This is my python script:
# coding=utf-8
import sys
print '1'
print '--INPUT--'
inum = sys.stdin.readline()
print '2'
print '--EOF--'
I tried running my code
sevenTry("python", "C:\\Testing.py");
but on java side it get stuck inside tReader at line:
String line = reader.readLine();
The program does work if i take out the input line from the python file
inum = sys.stdin.readline()
Using
inum = raw_input()
still bring up the same problem (im using python 2.7)
The most confusing part here that i even tried to test this with a java file (instead of python)
sevenTry("java", "-classpath", "C:\\class", "CheckCMD");
and it worked even with the input lines
import java.util.Scanner;
public class CheckCMD {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String line;
System.out.println("1");
System.out.println("--INPUT--");
in.hasNext();
line = in.nextLine();
System.out.println("2");
System.out.println("--EOF--");
}
}
As you may have noticed, this is a problem related to Python.
As described in https://unix.stackexchange.com/questions/182537/write-python-stdout-to-file-immediately,
" when process STDOUT is redirected to something other than a terminal, then the output is buffered into some OS-specific-sized buffer (perhaps 4k or 8k in many cases)."
So, you need to call sys.stdout.flush() after each invoke to print.
Or, as a better option, you can change the default behaviour for the process, using the -u param, to get unbuffered output.
I made my one-on-one socket chat work between the server (myself) and the client (a friend in a different network). Now I'm trying to do the same but I'm trying to create multiple connections, placing them in an Executors.newFixedThreadPool(poolSize), where part of the code is taken from the ExecutorService documentation.
The server works, and accepts connections, however, the problem occurs when I try to make a second connection and send messages to it. Although each client can send messages to the server, the server can only send messages to the first client.
Here is the full code:
public class MultipleServer implements Runnable {
private final ServerSocket serverSocket;
private final ExecutorService pool;
Scanner console;
public MultipleServer(int port, int poolSize, Scanner mainconsole)
throws IOException {
serverSocket = new ServerSocket(port);
pool = Executors.newFixedThreadPool(poolSize);
console = mainconsole;
}
public void run() {
try {
for(;;) {
pool.execute(new Handler(serverSocket.accept(), console));
}
} catch (IOException ex) {
pool.shutdown();
}
}
}
class Handler implements Runnable {
private Socket socket;
private Scanner console;
private String name = "undefined";
Handler(Socket socket, Scanner console)
{
this.socket = socket;
this.console = console;
}
public void run()
{
if (socket.isConnected())
{
System.out.println("connection from " + socket.getLocalAddress().getHostAddress());
Thread inputthread = new Thread(new Runnable()
{
#Override
public void run()
{
PrintWriter out;
try
{
out = new PrintWriter(socket.getOutputStream(), true);
out.println("Welcome to my server. Input your name");
out.flush();
String line;
while ((line = console.nextLine()) != null)
{
if (line.contains("/"))
{
if (line.equals("/q " + name))
{
out.println("Connection closing");
System.out.println("Connection to " + name + "closing");
out.close();
socket.close();
} else if (line.substring(0, name.length() + 3).equals("/m " + name))
{
out.println(line.substring(name.length() + 4));
out.flush();
}
} else
{
System.out.println("Incorrect command");
}
}
if (socket.isClosed())
{
out.close();
}
} catch (IOException e)
{
e.printStackTrace();
}
}
});
Thread outputthread = new Thread(new Runnable()
{
int msgno = 0;
#Override
public void run()
{
BufferedReader in;
try
{
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (!socket.isClosed())
{
while (!in.ready())
{
Thread.sleep(100);
}
String msg = in.readLine();
if (msgno == 0)
{
name = msg;
msgno++;
} else
{
System.out.println(name + ": " + msg);
}
synchronized (this)
{
this.wait(100);
}
}
if (socket.isClosed())
{
in.close();
}
} catch (IOException e)
{
e.printStackTrace();
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
});
inputthread.start();
outputthread.start();
}
}
public static void main(String[] args) throws IOException
{
int connections = 10;
int port = 80;
Scanner scanner = new Scanner(System.in);
MultipleServer server = new MultipleServer(port, connections, scanner);
server.run();
}
}
More specifically, the exception thrown:
Exception in thread "Thread-2" java.lang.IndexOutOfBoundsException: end
at java.util.regex.Matcher.region(Unknown Source)
at java.util.Scanner.findPatternInBuffer(Unknown Source)
at java.util.Scanner.findWithinHorizon(Unknown Source)
at java.util.Scanner.nextLine(Unknown Source)
at Handler$1.run(MultipleServer.java:61)
at java.lang.Thread.run(Unknown Source)
Where the line in question is:
while((line=console.nextLine())!=null){
To clarify: this exception happens when the second user joins the server. When I type /m user1 message the first user gets the intended message, when I type /m user2 message, there are no errors, but the user2 doesn't get the message. Moreover, there is no "Incorrect command" message at the server console, meaning that the output to the second user isnt working
The main problem - you have too complicated threads management: several threads tries to read from console input simultaneously: user 1 reader thread and user 2 read thread.
You should introduce a single router thread, responsible for communication with administrator and manage all messages between spawned threads via shared concurrent structure(s).
For such tasks it would be better to use any existent frameworks, e.g. netty or nirvana messaging.
I have a Python app and a Java app running simultaneously.
I want Java to start the Python process and then communicate using the normal STDIN/STDOUT streams with Python.
I have started the process correctly and have two threads to handle the two I/O streams.
OUTPUT THREAD:
class output2 extends Thread {
Process process;
OutputStream stdin;
BufferedWriter writer;
Scanner in = new Scanner(System.in);
output2(Process p) {
try {
process = p;
stdin = process.getOutputStream();
writer = new BufferedWriter(new OutputStreamWriter(stdin));
} catch (Exception e) {
System.out.println("ERROR output2(): " + e);
}
}
#Override
public void run() {
System.out.println("Starting OUTPUT THREAD");
try {
while (true) {
String input = in.nextLine();
writer.write(input);
writer.flush();
}
} catch (Exception e) {
System.out.println("ERROR output2_run(): " + e);
}
System.out.println("Ending OUTPUT THREAD");
}
}
INPUT THREAD :
class input2 extends Thread {
Process process;
InputStream stdout;
BufferedReader reader;
input2(Process p) {
try {
process = p;
stdout = process.getInputStream();
reader = new BufferedReader(new InputStreamReader(stdout));
} catch (Exception e) {
System.out.println("ERROR input2(): " + e);
}
}
#Override
public void run() {
System.out.println("Started INPUT THREAD");
try {
while (true) {
System.out.println(Thread.currentThread().getName() + " is executing");
if (reader.readLine() != null) {
System.out.println("Stdout: " + reader.readLine());
}
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + " stopped executing");
}
} catch (Exception e) {
System.out.println("ERROR input2_run(): " + e);
}
System.out.println("Ending INPUT THREAD");
}
}
MAIN :
public class My_Java {
public static void main(String args[]) {
File file = new File("C:\\Location\\");
try {
Process process = Runtime.getRuntime().exec("C:\\Python27\\python.exe chat_from_file.py", null, file);
input2 input = new input2(process);
output2 output = new output2(process);
input.setName("INPUT THREAD");
output.setName("OUTPUT THREAD");
input.start();
output.start();
} catch (Exception e) {
System.out.println("ERROR main(): " + e);
}
}
}
This doesn't seem to give any response at all.
It starts both threads, says INPUT THREAD is executing but nothing after that.
Where am I going wrong?
First of all, after calling if (reader.readLine() != null) { in your input class, you effectively have read the line and the next call will return null.
Use ready to check for non-blocking read possibility. Don't read upfront.
However, I'm pretty sure that you process exists abnormally, with something like python: can't open file 'chat_from_file.py': [Errno 2] No such file or directory or, throws a stacktrace and exits.
Use getErrorStream to check what the process is outputting if an error exists. This will put you on the correct path to solve your issue.
Also, just in case, make sure there's actually something to be read. Make sure your Python application is outputting enough data for buffers to be flushed (or flushing its writes).
And don't forget to join and exit cleanly and correctly. Good luck.
Here is the code:
public static void main(String[] args) {
SocketWorker worker = null;
MyIOConsole mio = null;
try {
portNumber = 2012;
worker = new SocketWorker();
worker.assignPort(portNumber);
mio = new MyIOConsole();
mio.assignObject(worker);
Thread b = new Thread(mio);
b.start();
worker.run();
} catch (IOException e) {
e.printStackTrace();
}finally{
mio.applicationQuit();
}
}
The SocketWorker is simply a socket, listening the port 2012, and the MyIOConsole, will accept user command,
public class MyConsoleIO implements Runnable {
SocketWorker o;
static BufferedReader reader;
public void assignObject(Object o) {
reader = new BufferedReader(new InputStreamReader(System.in));
this.o = (SocketWorker) o;
}
#Override
public void run() {
String inputString = null;
System.out.println("Press 'q' to kill to program");
try {
inputString = reader.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (inputString.equalsIgnoreCase("q")) {
this.applicationQuit();
}
}
public void applicationQuit(){
this.o.stopWorking();
System.exit(0);
}
}
But when the Socket got the exception, even I catch them, the code
mio.applicationQuit();
keep run. I don't want that, I just want when the user close or crashed the application, the socket will close and quit. How can I solve it?
Add the following. The run method will be called as the JVM is exiting.
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run(){
// cleanup code before JVM exit goes here.
}
});
I am trying to call a simple program test.exe which is as simple as-
int main()
{
int a;
cout<<"Welcome\n";
while(cin>>a&&a!=0)
cout<<"you entered "<<a<<endl;
}
I want to run it from a java program as a process, and send+recieve i/o from it. I am using the process with 2 threads as follows-
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Processproblem {
public static void main(String[] args)throws IOException, InterruptedException {
final Process process;
try {
process = Runtime.getRuntime().exec("test.exe");
} catch (IOException e1) {
e1.printStackTrace();
return;
}
new Thread(new Runnable() {
public void run() {
String line;
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
try {
while ((line = br.readLine()) != null) {
System.out.println("[OUT] " + line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
public void run() {
try {
byte[] buffer = new byte[1024];
int reading=0;
System.out.println(reading);
BufferedWriter bw= new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
while(reading!=-1)
{
reading= System.in.read(buffer);
for(int i = 0; i < buffer.length; i++) {
int intValue = new Byte(buffer[i]).intValue();
if (intValue == 0) {
reading = i;
break;
}
else
{
bw.append((char)intValue);
}
}
bw.newLine();
bw.flush();
}
} catch (Exception e) {
}
}
}
).start();
}
}
But they are not working as expected. When i run the program it just shows the "Welcome\n" message and then stops for input. When i give a integer and press enter in the java console it does nothing.
What am I doing wrong? They are two separate threads so why are they blocking each other? Is there any problem in my concept?
The program waits for your input. Grab the process output stream (using getOutputStream) and write to it.