Abh*_*bhi 7 java mobile multithreading deadlock java-me
下面简单的midlet代码(类Moo)(在摘录之后)死锁(至少我认为在这里阅读这篇帖子之后它会死锁).
我转载了帖子的相关摘录:
String url = ...
Connection conn = null;
try {
conn = Connector.open( url );
// do something here
}
catch( IOException e ){
// error
}
问题的根源是open()调用的阻塞性质.在某些平台上,系统在封面下进行实际连接,相当于单独的线程.调用线程阻塞,直到连接线程建立连接.同时,安全子系统可能要求用户确认连接,并且连接线程阻塞,直到事件线程得到用户的确认.发生死锁是因为事件线程已经在等待连接线程.
public class Moo extends MIDlet {
protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
// TODO Auto-generated method stub
}
protected void pauseApp() {
}
protected void startApp() throws MIDletStateChangeException {
Display display = Display.getDisplay(this);
MyCanvas myCanvas = new MyCanvas();
display.setCurrent(myCanvas);
myCanvas.repaint();
}
class MyCanvas extends Canvas {
protected void paint(Graphics graphics) {
try {
Image bgImage = Image.createImage(getWidth(), getHeight());
HttpConnection httpConnection = (HttpConnection) Connector
.open("http://stackoverflow.com/content/img/so/logo.png");
Image image = Image.createImage(httpConnection
.openInputStream());
bgImage.getGraphics().drawImage(image, 0, 0, 0);
httpConnection.close();
graphics.drawImage(bgImage, 0, 0, 0);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
有人可以告诉我如何在这里完成系统线程调用(事件和通知线程)以及导致死锁的事件序列.我不清楚这里涉及到导致死锁的线程是什么.
编辑:在上面的代码中,我得到了逻辑.但是下面的代码应该至少可行吗?这个也在我在一个单独的线程中进行网络连接的地方死锁.
public class Foo extends MIDlet {
protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
// TODO Auto-generated method stub
}
protected void pauseApp() {
// TODO Auto-generated method stub
}
protected void startApp() throws MIDletStateChangeException {
Display display = Display.getDisplay(this);
MyCanvas myCanvas = new MyCanvas();
display.setCurrent(myCanvas);
myCanvas.repaint();
}
class MyCanvas extends Canvas {
protected void paint(Graphics graphics) {
try {
Image bgImage = Image.createImage(getWidth(), getHeight());
FetchImage fetchImage = new FetchImage();
Thread thread = new Thread(fetchImage);
thread.start();
thread.join();
bgImage.getGraphics().drawImage(fetchImage.image, 0, 0, 0);
graphics.drawImage(bgImage, 0, 0, 0);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class FetchImage implements Runnable {
public Image image;
public void run() {
HttpConnection httpConnection;
try {
httpConnection = (HttpConnection) Connector
.open("http://10.4.71.200/stage/images/front/car.png");
image = Image.createImage(httpConnection.openInputStream());
httpConnection.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
我在哪里可以获得j2me系统类的源代码(我想查看Connection类的实现)?
你不能.它实际上依赖供应商.诺基亚处理这种情况的方式可能与摩托罗拉有所不同.
您必须学习的教训是,不要在系统回调中进行昂贵的计算,因为这可能会使系统无响应.因此,将耗时的操作放在一个单独的线程中,并始终尽早从回调中返回.
即使你在第二个例子中创建了一个单独的线程,你还是等待它在paint()中的完成,它最终会产生没有线程的结果!
你能做的一件事是
class MyCanvas extends Canvas {
Image image;
boolean imageFetchFailed;
protected void paint(Graphics g) {
if (image == null) {
fetchImage();
g.drawString("Fetching...", getWidth() >> 1, getHeight() >> 1, Graphics.HCENTER | Graphics.TOP)
} else if (imageFetchFailed) {
g.drawString("Failed to fetch image", getWidth() >> 1, getHeight() >> 1, Graphics.HCENTER | Graphics.TOP)
} else {
g.drawImage(image, 0, 0, 0);
}
}
private void fetchImage() {
new Thread(new Runnable() {
public void run() {
HttpConnection httpConnection = null;
try {
httpConnection = (HttpConnection) Connector
.open("http://10.4.71.200/stage/images/front/car.png");
image = Image.createImage(httpConnection.openInputStream());
} catch (IOException e) {
e.printStackTrace();
imageFetchFailed = true;
}
if (httpConnection != null) {
try {
httpConnection.close();
} catch (IOException ignored) {
}
}
// Following will trigger a paint call
// and this time image wont be null and will get painted on screen
repaint();
}
}).start();
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4307 次 |
最近记录: |