简单的midlet代码(类Moo)下面(摘录后)死锁(至少我认为在线程
here上阅读这篇文章后死锁).
我转载了帖子的相关摘录:
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("https://stackoverflow.com/content/img/so/logo.png"); Image image = Image.createImage(httpConnection .openInputStream()); bgImage.getGraphics().drawImage(image,0); httpConnection.close(); graphics.drawImage(bgImage,0); } catch (IOException e) { e.printStackTrace(); } } } }
有人可以告诉我如何在这里完成系统线程调用(事件和通知线程)以及导致死锁的事件序列.我不清楚这里涉及到导致死锁的线程是什么.
>有关于j2me线程模型的文档吗?
>我在哪里可以获得j2me系统类的源代码(我想查看Connection类的实现)?
编辑:在上面的代码中,我得到了逻辑.但是下面的代码应该至少可行吗?这个也在我在一个单独的线程中进行网络连接的地方死锁.
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); graphics.drawImage(bgImage,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(); } } } }
解决方法
Where can I get the sources for
j2me system classes (I want to check
out the implementation of Connection
classes)?
你不能.它实际上依赖供应商.诺基亚处理这种情况的方式可能与摩托罗拉有所不同.
您必须学习的教训是,不要在系统回调中进行昂贵的计算,因为这可能会使系统无响应.因此,将耗时的操作放在一个单独的线程中,并尽可能早地从回调中返回.
即使你在第二个例子中创建了一个单独的线程,你也要等待它在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",Graphics.HCENTER | Graphics.TOP) } else { g.drawImage(image,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(); } }