You Are Here:

Community: Developer Discussion Boards

#1 Old wait() and notify() - 2004-01-19, 17:55

Join Date: Aug 2003
Posts: 68
jhodgski
Offline
Regular Contributor
Hello,

I am trying to create a test midlet that performs httpconnections in a new, separate thread (so it will run on my 7650). The main thread waits for the new thread to finish, and the main thread then displays a results screen.

Initially, the new thread dd seem do its stuff, but then the main thread would not resume and execute any code after the wait() line.

But now I've been playing around with it so much I am getting an IllegalMonitorStateException.

Here is my code. Any help would be greatly appreciated.

Thanks,
James

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.io.*;
import javax.microedition.io.*;

public class OtaThreadTestMIDlet extends MIDlet implements CommandListener {

private Command commandExit, commandOK, commandHome; // The exit command
private Display display; // The display for this MIDlet
private Form f;
private String[] urls, results;
private HttpConnection con;
private InputStream in;
private Gauge g;
private Object mutex = new Object();
private OtaThread otaT;
private String[] resultsStrings;

public OtaThreadTestMIDlet() {
System.err.println("now in OtaThreadTestMIDlet constructor");
display = Display.getDisplay(this);
commandExit = new Command("Exit", Command.SCREEN, 2);
commandOK = new Command("OK", Command.BACK, 0);
commandHome = new Command("Home", Command.BACK, 0);
urls = new String[2];
urls[0] = ""; //enter first url here
urls[1] = ""; //enter second url here, etc
}

public void startApp() {
System.err.println("now in startApp()");
createInstructionsScreen();
}

private void createInstructionsScreen() {
System.err.println("now in createInstructionsScreen()");
f = new Form("Instructions!");
f.append("Press OK to get data ota from:");
for (int i = 0; i < urls.length; i++) {
f.append("\n\n");
f.append(urls[i]);
}

f.addCommand(commandOK);
f.addCommand(commandExit);
f.setCommandListener(this);

display.setCurrent(f);
}

public void pauseApp() {
}

public void destroyApp(boolean unconditional) {
}

public void commandAction(Command c, Displayable s) {
if (c == commandOK) {
Form resultsForm = new Form("Results");
resultsForm.setCommandListener(this);
otaT = new OtaThread(urls, mutex, this);
otaT.setPriority(Thread.MAX_PRIORITY); //(This line doesn't give the desired effect)
//synchronized (this){ //synchronized (mutex) {
synchronized (this) {
otaT.start();
try {
wait(); //mutex.wait();
}
catch(InterruptedException ie) {
System.err.println("InterruptedException: " + ie.getMessage());
}
}
resultsForm = new Form("Results");
resultsForm.append("And the results are:");
for (int i = 0; i < results.length; i++) {
resultsForm.append("\n\n");
resultsForm.append(results[i]);
}
resultsForm.addCommand(commandExit);
resultsForm.addCommand(commandHome);
display.setCurrent(resultsForm);
}
else if (c == commandHome) {
createInstructionsScreen();
}
else if (c == commandExit) {
destroyApp(false);
notifyDestroyed();
}
}


public class OtaThread extends Thread {
private String[] urls;

private Form resultsForm;
private OtaThreadTestMIDlet o;
private Object mutex;

//Constructor
OtaThread(String[] urls, Object mutex, OtaThreadTestMIDlet o) {
this.urls = urls;
this.mutex = mutex;
this.o = o;
}

public void run() {
synchronized (o) {
try {
resultsStrings = getStringsFromUrls(urls);
}
catch(Exception e) {
System.err.println("Exception: " + e.toString() + " - " + e.getMessage());
e.printStackTrace();
}
o.notify(); //mutex.notify();
}
}

private String[] getResultsStrings() {
return resultsStrings;
}

//This method takes an array of urls and returns an array of strings (obtained from the urls)
private String[] getStringsFromUrls(String[] urls) throws Exception {;
for (int i = 0; i < urls.length; i++) {
System.err.println("urls[" + i + "]: " + urls[i]);
}
String[] returnStringArray = new String[urls.length];
StringBuffer sBReturn;

Form progressForm = new Form("Please wait");
g = new Gauge("Contacting Server", false, 100, 0); //g is the progress gauge
progressForm.append(g);
display.setCurrent(progressForm);

try{
for (int u = 0; u < urls.length; u++) {
sBReturn = new StringBuffer();
con = (HttpConnection)Connector.open(urls[u]);
in = con.openInputStream();
if (g.getValue() == 0) g.setValue(100 / (urls.length + 1));
int len = (int)con.getLength();
if (len > 0) {
byte[] bytes = new byte[len];
int actual = in.read(bytes);
returnStringArray[u] = new String(bytes);
}
else {
int ch;
while ((ch = in.read()) != -1) {
sBReturn.append((char)ch);
}
returnStringArray[u] = sBReturn.toString();
}
g.setValue(100 * (u + 2) / (urls.length + 1));
} //next url
}
finally {
try {
if (in != null)
in.close();
if (con != null)
con.close();
}
catch (IOException ioe) {
System.err.println("IOException: " + ioe.getMessage());
}
}
return returnStringArray;
}
}
}
Reply With Quote

#2 Old 2004-01-19, 18:14

Join Date: Jan 2004
Posts: 25
dleeICT
Offline
Registered User
do you not have to declare the commandAction method as synchronized as well?

public synchronized void commandAction(Command c, Displayable s) {
Reply With Quote

#3 Old 2004-01-19, 18:23

Join Date: Aug 2003
Posts: 68
jhodgski
Offline
Regular Contributor
Tried it but no joy. Thanks tho.
Reply With Quote

#4 Old 2004-01-19, 19:36

Join Date: Apr 2003
Posts: 61
aspaans
Offline
Regular Contributor
It is not a problem obtaining the lock. You execute both the wait and the notify in a synchronized block, both synchronized on the one and only MIDlet instance.

However, you seem to call the 'wait()' method while executing the commandAction. This holds the processing of not only your commandAction method, but may hold ALL event processing of your midlet-application. In your OtaThread, you create a Form. I don't know too much about how the J2ME of the 7650 dispatches events; If it uses only one thread per application for event-dispatching (regardless of the thread creating the displayable), your midlet is entered in a deadlock as soon as you create the Form in your OtaThread (since the wait() method of the main thread has stopped the event-dispatching).

Try to remove the Form with the progress-bar (remove *all* User interface code) and see what happens.

Since you call wait() in your main thread anyway, why not just obtain the URLs data in your main thread?

-- Anton
Reply With Quote

#5 Old 2004-01-21, 16:35

Join Date: Mar 2003
Posts: 33
niekvs
Offline
Registered User
What you are doing doesn't make any sense: you're starting a new Thread, and then wait for it to finish. Why start a new Thread then? The point of Threads is that you can increase concurrency by doing multiple things at once. But you're doing only one thing at a time, so instead of creating the new Thread, you could just as well (better) just call the run method directly. (and call it something else probably)

However, that wouldn't be good in this case, because you don't want to hold up the event thread. Event methods like commandAction(), paint(), etc. should return as quickly as possible. Any long term operations should be performed in another Thread. Which you did.. but you didn't see the point, because you're waiting for it to finish in the same event Thread. So the whole purpose of spawning a new Thread is gone.

One way to fix all this would be to do the long-term processing in another Thread; *not* wait for it to finish, and then use a listener approach to notify the Form to display the results. To see what i'm talking about, read the following article, which describes a very similar problem, and solution: http://today.java.net/pub/a/today/2003/10/24/swing.html

Have fun!
-- Niek
Last edited by niekvs : 2004-01-22 at 01:33.
Reply With Quote

#6 Old 2004-01-21, 17:01

Join Date: Apr 2003
Posts: 61
aspaans
Offline
Regular Contributor
Here is a similar example as the one that Niekvs gave (using listeners). But this one is for MIDlets. You can almost copy and paste code in this example:

http://www.forum.nokia.com/main/1,65...ml&fileID=2642

-- Anton.
Reply With Quote

#7 Old 2004-01-22, 12:39

Join Date: Aug 2003
Posts: 68
jhodgski
Offline
Regular Contributor
Cheers guys, and thanks for the links.

The reason I need a new thread for the http stuff owes to a bug on the 7650. If you try and do the httpconnection stuff in the main thread, the midlet hangs, so that's why the new thread.

Incidentally, I also tried using Thread's join() method instead of wait() and notify(), but that performed really poorly on the 7650.

I will gives those links a read.

Many thanks,
James
Reply With Quote

#8 Old 2004-06-11, 10:40

Join Date: Mar 2004
Posts: 37
diplm
Offline
Registered User
Hi,

unefortunately I can't find this article (http://www.forum.nokia.com/main/1,6...tml&fileID=2642) on forum.nokia. Is it still available? Or could someone send it to me (inselschaaf@gmx.net).

Many thanks,
Heike
Reply With Quote
Reply « Previous Thread | Next Thread »
Display Modes
Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules

You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are Off
[IMG] code is Off
HTML code is Off
Forum Jump

Rate This

 
Bookmark this page: DeliciousDiggFacebookGoogleYahooStumbleUponRedditDiigoTechnocratiTwitter  Share this page Share this page Print this Page Print this page Invite a friend Invite a friend
京ICP备05048969号    Email Newsletters Press Terms & Conditions Privacy Policy Sitemap Contact Us © 2009 Nokia