How can I read from the same files with multiple threads? - java

I'm trying to use multiple threads while using my "runClient" method.
"runClient" connects to the localhost, and the server uses the "handleClient" function to do the calculations.
I believe the handleClient is where the problem is, as there is nothing that controls concurrency or anything synchronized, but i'm not sure how exactly to implement what I need and if it should even be there or somewhere else in the code.
Thread t1 = new Thread(()->runClient(port, "Q,s1.txt,s2.txt,"+s1[1], true));
t1.start();
Thread t2 = new Thread(()->runClient(port, "Q,s1.txt,s2.txt,"+s2[4], true));
t2.start();
public static void runClient(int port,String query,boolean result) {
try {
Socket server=new Socket("localhost",port);
PrintWriter out=new PrintWriter(server.getOutputStream());
Scanner in=new Scanner(server.getInputStream());
out.println(query);
out.flush();
String res=in.next();
if((result && !res.equals("true")) || (!result && !res.equals("false")))
System.out.println("problem getting the right answer from the server (-10)");
in.close();
out.close();
server.close();
} catch (IOException e) {
System.out.println("your code ran into an IOException (-10)");
}
}
public void handleClient(InputStream inFromClient, OutputStream outToClient) {
DictionaryManager dictionaryManager = DictionaryManager.get();
try {
BufferedReader br = new BufferedReader(new InputStreamReader(inFromClient));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(outToClient));
String line = br.readLine();
String filesAndQuery = line.substring(2);
String[] clientWords = filesAndQuery.split(",");
if (line.charAt(0) == 'Q') {
if (dictionaryManager.query(clientWords))
bw.write("true\n");
else
bw.write("false\n");
}
if (line.charAt(0) == 'C') {
if (dictionaryManager.challenge(clientWords))
bw.write("true\n");
else
bw.write("false\n");
}
bw.close();
br.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
I get the following error:
Exception in thread "Thread-3" java.util.NoSuchElementException
at java.base/java.util.Scanner.throwFor(Scanner.java:941)
at java.base/java.util.Scanner.next(Scanner.java:1482)
at test.MainTrain3.runClient(MainTrain3.java:128)
at test.MainTrain3.lambda$testBSCH$1(MainTrain3.java:157)
at java.base/java.lang.Thread.run(Thread.java:833)
What could be the reason? How should I fix it?

Related

Resource leak in my java program

I am trying to write a method in java, where I take some information from a file and see if the file has the information the user looks for. However, for the code that I present, eclipse signs that I have an resource leak in line "return true;" and that the "br = new BufferedReader(fr);" is never close, despite the fact that I am using the close() method at the end of the program. Apparently I am missing something. Could someone help me figure out what is happening? Great thanks in advance!
import java.io.*;
class Help{
String helpfile;
Help(String fname){
helpfile = fname;
}
boolean helpon(String what){
FileReader fr;
BufferedReader br;
int ch;
String topic, info;
try{
fr = new FileReader(helpfile);
br = new BufferedReader(fr);
}
catch(FileNotFoundException e){
System.out.println(e);
return false;
}
try{
do{
ch = br.read();
if(ch=='#'){
topic = br.readLine();
if(what.compareTo(topic) == 0){
do{
info = br.readLine();
if(info!=null)
System.out.println(info);
}while((info!= null) && (info.compareTo("")!= 0));
return true;
}
}
}while(ch!=-1);
}
catch(IOException e){
System.out.println(e);
return false;
}
try{
br.close();
}
catch(IOException e){
System.out.println(e);
}
return false;
}
}
The issue is that you're returning before the program gets the chance to close the resource. There are 2 ways to fix this issue:
Put the returns after you close the resource (by possibly putting the return result in a boolean).
Modify your code to put the close in a finally block so any return done will still execute that code.
Number 2 is generally a more accepted practice because then if you add more things in the future you are still guaranteed to close the resource (unless a catastrophic event occurs).
boolean helpon(String what){
FileReader fr;
BufferedReader br;
int ch;
String topic, info;
try{
fr = new FileReader(helpfile);
br = new BufferedReader(fr);
do{
ch = br.read();
if(ch=='#'){
topic = br.readLine();
if(what.compareTo(topic) == 0){
do{
info = br.readLine();
if(info!=null)
System.out.println(info);
}while((info!= null) && (info.compareTo("")!= 0));
return true;
}
}
}while(ch!=-1);
} catch(IOException e){
System.out.println(e);
return false;
} catch(FileNotFoundException e){
System.out.println(e);
return false;
} finally {
try {
if (br != null) {
br.close();
}
} catch(IOException e){
System.out.println(e);
return false;
}
}
}
You have return statements all over the method, but only have a br.close() at the end. It's possible in the flow of code that the method will be returned leaving the br still open.
You may be interested in using try with resources
try (
FileReader fr = new FileReader(helpfile);
BufferedReader br = new BufferedReader(fr)
)
{
//your code
}
catch (IOException e)
{
//error
}
With this, the close methods will automatically be called for you on the resources.
You should put the call to close() in a finally block. In the current state, your code will never reach the final try/catch because you are returning true or false.
try {
fr = new FileReader(helpfile);
br = new BufferedReader(fr);
do {
ch = br.read();
if(ch=='#'){
topic = br.readLine();
if(what.compareTo(topic) == 0){
do{
info = br.readLine();
if(info!=null)
System.out.println(info);
}while((info!= null) && (info.compareTo("")!= 0));
return true;
}
}
}while(ch!=-1);
} catch (IOException e) {
System.out.println(e);
return false;
} catch (FileNotFoundException e) {
System.out.println(e);
return false;
} finally {
try {
if (br != null) {
br.close();
}
} catch (IOException e) {
System.out.println(e);
}
}
If you're using Java 7, use the try-with-resources functionality:
http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

Change application behaviour if a thread sends a signal

I wrote this simple code :
class main{
public static void main(String []a)throws UnknownHostException,IOException{
Scanner sc = new Scanner(System.in);
int choice;
ServerSocket ss = new ServerSocket(60000,1,InetAddress.getLocalHost());
Thread t = new Thread(new Conversation(ss));
t.start();
while(true){// I think i need to set a better condition here
do{
System.out.println("Hello user choose a number between 0 and 2");
}
while(!sc.hasNextInt());
choice = sc.nextInt();
if(choice >2 || choice < 0)
choice = 0;
switch(choice){
case 0:
//print some stuff
break;
case 1:
//print other stuff
break;
case 2:
//print new stuff
break;
default:
break;
}
}
}
}
And heres the code of the class Conversation :
public class Conversation implements Runnable {
ServerSocket ss;
Socket client;
boolean connected;
Conversation(ServerSocket cli){
this.ss= cli;
client = null;
connected = false;
}
void connected(){
this.connected = true;
}
void disconnected(){
this.connected = false;
}
#Override
public void run() {
// TODO Auto-generated method stub
while(true) {
PrintWriter pw = null;
if(!this.connected){
try {
client = ss.accept();
pw =new PrintWriter(client.getOutputStream(),true);
this.connected();
} catch (IOException e) {
System.err.println("Accept failed.");
System.err.println(e);
System.exit(1);
}
BufferedReader in = null;
PrintWriter out = null;
try {
in = new BufferedReader(new InputStreamReader(
client.getInputStream()));
out = new PrintWriter(client.getOutputStream(), true);
} catch (IOException e) {
System.err.println(e);
return;
}
String msg;
try {
while ((msg = in.readLine()) != null) {
if(msg.equals("CLO") || msg.equals("clo")){// if a CLO message is sent the conversation ends
client.close();
in.close();
out.close();
pw.close();
this.disconnected();
break;
}
else{
System.out.println("Client says: " + msg.substring(7));
}
}
} catch (IOException e) {
System.err.println(e);
}
}
}
}
}
Basically all it does is to wait for a user input and then prints something according to what he typed.
The problem I'm facing is:
I want that when someone connects to the ServerSocket ss in the thread t(so the value of connected is true)I want the main function to stop whatever it is doing and to just send the user input into the OutputStream of the socket client(so in other words starting a chat when someone connects to the ServerSocket).
But i don't know how to do so I'm new in Threading and networks in Java , is there a way for the thread T to send a signal to the main function of the main class or does anybody have an idea of how to achieve this ?
I have already posted some samples code in the same context. Please have a look at below samples and try to follow each and every step to understand it. Read inline comments carefully.
Multiple clients access the server concurrently
Java Server with Multiclient communication.
Server-Client chat program
please let me know if there is any confusion.

how to run .exe file of a java file in other computers

I have developed a java code in eclipse.My code reads data from a .txt file by using server_ip. I have created an executable jar file of the code and then created an .exe file using launch4j. The .exe file shows data if I run it in my laptop,but it does not show any data if I run it in other pc. then it shows null point exception. my operating system is windows 7-32 bit. I am giving my code here. please give me solutions.
package remotedata;
import java.awt.*;
import java.net.;
import java.io.;
public class remotedataread extends Frame
{
public static void main(String[] args)
throws InterruptedException, IOException{
BufferedReader br = null;
TextArea FileText =
new TextArea(" Content of the File \'temp1.txt\' :");
try
{
URL url =
new URL("file://server_ip/path_file.txt");
InputStream is = url.openStream();
br = new BufferedReader(new InputStreamReader(is));
/* String line = null;
while (true) {
line = br.readLine();
if (line == null) {
//wait until there is more of the file for us to read
Thread.sleep(1000);
}
else {
System.out.println(line);
}
}*/
}
catch (MalformedURLException e)
{
System.out.println("Bad URL");
}
catch (IOException e)
{
System.out.println("IO Error : "+e.getMessage());
}
FileText.setBackground(Color.white);
FileText.append(String.valueOf('\n'));
Frame f = new Frame("server data");
f.setSize(200,200);
f.add(FileText);
f.setVisible(true);
try
{
String s;
s=null;
boolean eof = false;
//while (true) {
s = br.readLine();
System.out.println("Time Temperature");
while( !eof )
{
FileText.append(s + String.valueOf('\n'));
try
{
s = br.readLine();
if ( s == null )
{
// eof = true;
// br.close();
Thread.sleep(1000);
}
else{
//System.out.println("Time Temperature");
System.out.println(s);
}
}
catch (EOFException eo)
{
eof = true;
}
catch (IOException e)
{
System.out.println("IO Error : "+e.getMessage());
}
}
//}
}
catch (IOException e)
{
System.out.println("IO Error : "+e.getMessage());
}
}
}
Maybe , you're application is not able to connect to the other node ..hence its throwing a NullPointer exception .Make sure that computers are in the Network
your prolem seems to be here:
URL url =
new URL("file://server_ip/path_file.txt");
InputStream is = url.openStream();
br = new BufferedReader(new InputStreamReader(is));
the url "file://server_ip/path_file.txt" is valid on your laptop, but not on other pc's

how to read from standard input non-blocking?

long end=System.currentTimeMillis()+60*10;
InputStreamReader fileInputStream=new InputStreamReader(System.in);
BufferedReader bufferedReader=new BufferedReader(fileInputStream);
try
{
while((System.currentTimeMillis()<end) && (bufferedReader.readLine()!=null))
{
}
bufferedReader.close();
}
catch(java.io.IOException e)
{
e.printStackTrace();
}
I actually tried doing the above for reading in 600 miliseconds time after which it should not allow reading but the readline of the bufferedreader is blocking.Please help
Using BufferedReader.available() as suggested by Sibbo isn't reliable. Documentation of available() states:
Returns an estimate of the number of bytes that can be read... It is never correct to use the return value of this method to allocate a buffer.
In other words, you cannot rely on this value, e.g., it can return 0 even if some characters are actually available.
I did some research and unless you are able to close the process input stream from outside, you need to resort to an asynchronous read from a different thread. You can find an example how to read without blocking line by line here.
Update: Here is a simplified version of the code from the link above:
public class NonblockingBufferedReader {
private final BlockingQueue<String> lines = new LinkedBlockingQueue<String>();
private volatile boolean closed = false;
private Thread backgroundReaderThread = null;
public NonblockingBufferedReader(final BufferedReader bufferedReader) {
backgroundReaderThread = new Thread(new Runnable() {
#Override
public void run() {
try {
while (!Thread.interrupted()) {
String line = bufferedReader.readLine();
if (line == null) {
break;
}
lines.add(line);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
closed = true;
}
}
});
backgroundReaderThread.setDaemon(true);
backgroundReaderThread.start();
}
public String readLine() throws IOException {
try {
return closed && lines.isEmpty() ? null : lines.poll(500L, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
throw new IOException("The BackgroundReaderThread was interrupted!", e);
}
}
public void close() {
if (backgroundReaderThread != null) {
backgroundReaderThread.interrupt();
backgroundReaderThread = null;
}
}
}
You could check with BufferedReader.available() > 0 if there are chars to read.
String s;
while((System.currentTimeMillis()<end))
{
if (bufferedReader.available() > 0)
s += bufferedReader.readLine();
}
bufferedReader.close();
long end=System.currentTimeMillis()+60*10;
InputStreamReader fileInputStream = new InputStreamReader(System.in);
BufferedReader bufferedReader = new BufferedReader(fileInputStream);
try {
while ((System.currentTimeMillis() < end)) {
if (bufferedReader.ready()) {
System.out.println(bufferedReader.readLine());
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bufferedReader != null) {
bufferedReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
The only reliable way would be to start a worker thread and do the actual reading inside it, while the caller thread would monitor the latency.
If the worker thread is waiting longer that allowed, the master thread would terminate it and throw an exception.
BufferReader.readLine() can block for a very long time if a line is extremely long like 1M chars.
Does your file contains such long lines?
If yes, you may have to break up the lines, or use per-char read methods like BufferReader.read().

Reading streams from java Runtime.exec

I have the following snippet of code:
Process proc = runtime.exec(command);
errorGobbler = new ErrorStreamGobbler(proc.getErrorStream(), logErrors, mdcMap);
outputGobbler = new OutputStreamGobbler(proc.getInputStream(), mdcMap);
executor.execute(errorGobbler);
executor.execute(outputGobbler);
processExitCode = proc.waitFor();
where the gobblers are Runnables which use a BufferedReader to read the input and error streams of the executing process. While this works most of the time, I get the occasional window (of about 2 minutes or so) where I get the processExitCode as 0, which indicates normal termination but there is nothing in the input and error streams - nothing to even indicate end-of-stream.
Like I indicated before, this works most of the time but this failure occurs every once in a while - and I am totally puzzled. Any ideas?
Rags
I've struggled with the same kind of issues.
I can't remember what exactly was wrong (maybe I forgot to flush / close the streams correctly or something ...).
Anyway, here is what I came up with.
/**
* Handle communication with a process, reading its output/error and feeding its input
* #param process The process to execute
* #param _in Reader that will feed the input pipe of the process
* #param out Writer that will receive the output of the process
* #param err Writer that will receive the error pipe of the process
*/
public static void communicate(
Process process,
final Reader _in,
final Writer out,
final Writer err)
{
// Buffer the input reader
final BufferedReader in = new BufferedReader(_in);
// Final versions of the the params, to be used within the threads
final BufferedReader stdOut = new BufferedReader(new InputStreamReader(process.getInputStream()));
final BufferedReader stdErr = new BufferedReader(new InputStreamReader(process.getErrorStream()));
final BufferedWriter stdIn = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
// Thread that reads std out and feeds the writer given in input
new Thread() {
#Override public void run() {
String line;
try {
while ((line = stdOut.readLine()) != null) {
out.write(line + newline);
}
} catch (Exception e) {throw new Error(e);}
try {
out.flush();
out.close();
} catch (IOException e) { /* Who cares ?*/ }
}
}.start(); // Starts now
// Thread that reads std err and feeds the writer given in input
new Thread() {
#Override public void run() {
String line;
try {
while ((line = stdErr.readLine()) != null) {
err.write(line + newline);
}
} catch (Exception e) {throw new Error(e);}
try {
err.flush();
err.close();
} catch (IOException e) { /* Who cares ?*/ }
}
}.start(); // Starts now
// Thread that reads the std in given in input and that feeds the input of the process
new Thread() {
#Override public void run() {
String line;
try {
while ((line = in.readLine()) != null) {
stdIn.write(line + newline);
}
} catch (Exception e) {throw new Error(e);}
try {
stdIn.flush();
stdIn.close();
} catch (IOException e) { /* Who cares ?*/ }
}
}.start(); // Starts now
// Wait until the end of the process
try {
process.waitFor();
} catch (Exception e) {
throw new Error(e);
}
} // End of #communicate
I hope this helps.

Categories