I am sending a some json to a php page from my java application which echos "finished" if successful. The json and php are working great. I am trying to pass a string to a thread and then change the value of the string to the echo from the php in the thread, and when the Thread is finished I want to use an if statement to determine if the URL connection was successfully completed... which it is I just can't get the value of the string from the Thread.
here is my code:
main.java
final String line = "unfinished";
Thread iURL = new instrURL(line, jsonArray);
iURL.start();
while(iURL.isAlive())
{
System.out.println("In wait loop");
}
System.out.println(line);
if(line.trim() == "finished")
{
System.out.println("Made it to finished");
}
else
{
System.out.println("Did not make it to finished");
}
instrURL.java
public class instrURL extends Thread{
String line;
String jsonArray;
public instrURL(String line, String jsonArray)
{
this.line = line;
this.jsonArray = jsonArray;
}
public void run()
{
try
{
URL url = new URL("http://fake.php?jsonArray="+URLEncoder.encode(jsonArray, "UTF-8"));
URLConnection conn = url.openConnection();
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
line = rd.readLine();
System.out.println(line);
rd.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
the console:
In wait while loop
In wait while loop
...
...
...
In wait while loop
finished
In wait while loop
In wait while loop
In wait while loop
unfinished
Did not make it to finished
As you can see from the console the Thread gets the finished, but once outside of the Thread the strings value is still unfinished.
Any help would be greatly appreciated.
You have at least four different String reference variables with the name line in your process, and updates to one won't be reflected in the other ones, which is why your program doesn't behave as expected:
final String line = "unfinished"; in main.java - looks like a
local variable on the stack
instrURL(String line, - a paramter to
the instrURL constructor
instrURL.line a member in the instrURL
class
String line; a local in the run() method in instrURL
All of these are distinct references, so assigning to one will not affect any of the others. Even beyond that, I don't see any assignments at all to any of the flavors of line in the instrURL class.
Generally speaking you should use established inter-thread communication methods such as Future, or shared statics under a lock, but probably the closest thing to what you want is to declare a static volatile String line somewhere, and refer to it in both main and your thread class, and remove all other copies of line.
Java compare string with equals method not with ==
if(null!line && line.trim().equals("finished"))
{
System.out.println("Made it to finished");
}
Inside run method you are not reading data from buffered reader and not changing the value of line, that's why you are getting same value as "unfinished", you need to read data like this
String currentLine
while ((currentLine = br.readLine()) != null) {
System.out.println(sCurrentLine);
}
after reading data from stream , set value in line string as
line="finished";
Related
I have a class that calls a method from another class which uses a thread as it is somewhat a intensive task. The Thread is responsible for looking through a dictionary to find a matching word. When a word is found it should/does set a local variable in that class. I can see that it is successfully setting this String because it say's so in the log. However, whenever I try and retrieve this String from another class and set the TextView to the value of this String, Nothing happens.
I'm using the Thread because a lot of frames were being skipped. However, when I don't use the thread it works as it is suppose to(Minus the frames being skipped).
Here is the method with the thread:
public String checkLetters() {
new Thread(new Runnable() {
#Override
public void run() {
//Finding the directory on SD Card
File sdcard = Environment.getExternalStorageDirectory();
//Retrieve the text file
File file = new File(sdcard,"NewEnglishDictionary.txt");
try {
BufferedReader bufferRead = new BufferedReader(new FileReader(file),24396);
String line; //= "";
//While no word found keep looping
while (wholeWordFound == false ) {
line = bufferRead.readLine();
Log.d("ResolveWord", "Current Line: " + line);
wordReturned = workOutWord(line);
setWord(wordReturned);
}
String value = getWord().toString().toLowerCase();
Log.d("Value of setWord: ", " equals: "+ value);
bufferRead.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
return wordReturned;
}
And calling to retrieve the variable that has been set (according to the log)
tv_WordFound.setText(fixAnagram.getWord());
And the method which is suppose to return it:
public String getWord() {
Log.d("Test", "getWord: " + wordReturned);
return wordReturned;
}
Is there something I'm missing with threads?
Cheers for any help. Logcat itself gives me no clue to where the error lies.
you need to using callback or interface or asynctask for this case. Because your Thread inside checkLetters method will end after your checkLetters. That means if you call getWord() immediately after calling checkLetters, you can only get the previous checking result.
The Memory model of Java does not guarantee, that values set by one thread are immediately visible by another thread.
To guarantee this, you either must declare the variable as "volatile" or have a synchronized involved (e.g. have the getter and setter method with the keyword synchronized).
e.g.
private volatile String word;
or
public synchronized String getWord() { return word; }
public synchronized void setWord(String w) { word = w; }
I have a small java program, written in Eclipse using WindowBuilder, which works on reading data from UTF-8 text files and writing them into a database. To maintain the GUI's responsiveness, I use a swing worker thread, executed when clicking on a button.
btnex.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
worker = new SwingWorker<Void, Void>() {
public Void doInBackground() {
String[] content = Reader.getContent(file);
//do something with the content, if something goes wrong, set error to true.
return null;
}
public void done() {
if (!error) {
//handle error
}
};
worker.execute();
The function getContent in the class Reader extracts data from the file into the string array.
public static String[] getContent (String dbfile) {
try {
String[] lines = null;
String[] linesplit = null;
String store = "";
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(dbfile), "UTF8"));
String line = "";
line = reader.readLine();
linesplit = line.split(";");
while (linesplit.length > 1 && !line.equals(null)) {
for (int i = 0; i < linesplit.size(); i++) {
store += StringFormer.decrypt(linesplit[i]) + " ";
} //StringFormer is another class written by me, just for decrypting the string
store += "\n";
line = reader.readLine();
if (line.equals(null)) break;
linesplit = line.split(";");
}
reader.close();
lines = store.split("\n");
return lines;
} catch (Exception ex) { //...
}
}
When I try to run my program and click the button, the program does not work correctly. So I run the program in debug mode, and as a result, the thead does not finish but somehow exits before finishing all work. This happens in getContent, after leaving the while loop but before working on reader.close(). Before leaving the while loop, the call stack in the debug view contains the calls of the button click and of getContent, next to others, but once I leave the loop, the two mentioned above are dropped and the next top stack member names the base swing worker class: SwingWorker$2(FutureTask).run.
Does anyone know, why the program does not finish the written work flow? I work with multiple threads in the program, but never two background threads are running at the same time.
I found the answer myself:
The line if(line.equals(null) throws a NullPointerException. line is null when nothing more can be read out of the file, but the function equals requires that the compared variable is defined. Since line was null, equals threw the exception without me noticing it. The line has to be if(line==null).
This question already has answers here:
Using BufferedReader.readLine() in a while loop properly
(7 answers)
Closed 8 years ago.
I have problem with reading from my socket i read only if value isn't null but it doesnt't works.
#Override
public void run() {
System.out.println("Reading from socket");
while(true){
try {
if(!(br.readLine().equals(null)))read += br.readLine();
} catch (IOException e) {
System.out.println("error " + e);
}
}
}
here is error:
Exception in thread "Thread-4" java.lang.NullPointerException
at connection.CreateConnection.run(CreateConnection.java:61)
at java.lang.Thread.run(Unknown Source)
If br.readLine() returns null, then calling .equals(null) on it will throw an exception - it won't return true. You just want to compare reference identity with null.
Calling .equals(null) is never useful, unless you're testing that your equals implementation works properly :)
Additionally, you'll be skipping every other line by calling readLine() twice on each loop iteration.
You want something like:
String line;
if ((line = br.readLine()) != null) {
read += line;
}
... except that will be painfully slow due to repeated string concatenation. You should almost certainly be using a StringBuilder instead.
Also, doing all of this in a loop which catches IOException seems like a recipe for disaster - if the a call fails, it's very likely that it'll keep failing forever, whereupon your program is basically hung in a tight loop. You should almost certainly stop when you get an exception, rather than keeping going. For example:
try {
String line;
while ((line = reader.readLine()) != null) {
read += line; // Or builder.append(line);
}
} catch (IOException e) {
// Whatever you want to do
}
Finally, consider the value of whitespace, both horizontal and vertical, as well as the benefits of using braces even in single-statement if statements etc. The line if(!(br.readLine().equals(null)))read += br.readLine(); is compact at the expense of readability.
Say you are on the last line of your file, you call br.readLine() to check if it's not null. Your line exists so your test passes. Then you call br.readLine() once again. Unfortunately there is nothing left to read! And you get your exception.
Rewrite your code like that:
#Override
public void run() {
System.out.println("Reading from socket");
String line;
while(true){
try {
line = br.readLine()
if((line != null))read += line;
} catch (IOException e) {
System.out.println("error " + e);
}
}
}
You are calling .equals() on a null object, which causes the null pointer issue I assume. If you want to read with a buffered reader, try doing something like:
String line = reader.readLine();
while(line != null){
System.out.println(line);
line = reader.readLine();
}
This will eliminate the issue of null pointers, and will also stop you from skipping any lines during reading.
I have a Java Client/Server chat application and after a connection gets established, only about 1 quarter of the data is being received by the recipient. What could the problem be? Here is a print screen of what happens exactly:
Code for reading from socket:
public void somethingElse(){
try {
if(in.readLine() != null){
messageBufferIn = in.readLine();
System.out.println(in.readLine());
chat.append(recipient + ": " + messageBufferIn + "\n");
}
} catch (IOException e) {
e.printStackTrace();
}
}
Code for thread that runs above method:
public class chatListener extends Thread{
static main main = new main();
//static Thread mainThread = new Thread(main);
public void run(){
while(main.isConnected == true){
main.somethingElse();
}
}
}
The above thread gets run as soon as a connection gets established
Thanks for any help
Each time you call in.readLine, the scanner moves down to the next line; you can't keep calling it a few times, as it will skip the lines you never used essentially. Try this to replace somethingElse():
public void somethingElse(){
try {
String line;//Added a variable to store the current line to; readLine is
//dynamic, it returns the next line each call, so if we store to a variable,
//we only call it once, and hold that value
if((line = in.readLine()) != null){// (line = in.readLine()) != null is shorthand to store readLine to line, and then check if that returned value is null or not
System.out.println(line);//Print out the line
chat.append(recipient + ": " + line + "\n");//Append it
}
} catch (IOException e) {
e.printStackTrace();
}
}
Before, you were calling in.readLine once to check if it was null, then you saved the next line, then printed the next one. Hence the pattern of (fail success fail | fail success fail etc.) = Only messages 2 + 5 showing up
All sample function I've seen so far avoid, for some reason, returning a string. I am a total rookie as far as Java goes, so I am not sure whether this is intentional. I know that in C++ for example, returning a reference to a string is way more efficient than returning a copy of that string.
How does this work in Java?
I am particularly interested in Java for Android, in which resources are more limited than desktop/server environment.
To help this question be more focused, I am providing a code snippet in which I am interested in returning (to the caller) the string page:
public class TestHttpGet {
private static final String TAG = "TestHttpGet";
public void executeHttpGet() throws Exception {
BufferedReader in = null;
try {
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet();
request.setURI(new URI("http://www.google.com/"));
HttpResponse response = client.execute(request); // actual HTTP request
// read entire response into a string object
in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String line = "";
String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null) {
sb.append(line + NL);
}
in.close();
String page = sb.toString();
Log.v(TAG, page); // instead of System.out.println(page);
}
// a 'finally' clause will always be executed, no matter how the program leaves the try clause
// (whether by falling through the bottom, executing a return, break, or continue, or throwing an exception).
finally {
if (in != null) {
try {
in.close(); // BufferedReader must be closed, also closes underlying HTTP connection
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
In the example above, can I just define:
public String executeHttpGet() throws Exception {
instead of:
public void executeHttpGet() throws Exception {
and return:
return (page); // Log.v(TAG, page);
A String in java corresponds more or less to std::string const * in c++. So, it's cheap to pass around, and can't be modified after it's created (String is immutable).
String is a reference type - so when you return a string, you're really just returning a reference. It's dirt cheap. It's not copying the contents of the string.
In java most of the time you return something, you return it by reference. There's no object copying or cloning of any kind. So it is fast.
Also, Strings in Java are immutable. No need to worry about that either.