【讨论】贪吃蛇里到底有几个线程,怎么我只发现一个? 以前本人做过贪吃蛇的游戏(C++),现在正好在学java,我可以帮你看一下,你把代码发到我的信箱里:[email protected],我会尽快给你答复的 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 我不太了解j2me,但我可以帮你分析一下代码!!同上!! 你好,代码我看了一下,虽然我对j2me的midlet不太了解,但我认为此程序只有两个线程:main主线程-A和wormpit中的线程--B,主线程负责监听键盘事件,而线程B负责对界面进行重绘操作,因此程序中有很多的wait,notifyall,以及synchronized,下面我来解释一下为什么?由于线程A,B都会对一些变量进行访问如:gameOver,gamePaused,audioPlayer等,因此需要对他们进行同步的访问。 首先,程序出现了很多的同步块:而没有使用synchronized方法其格式为:synchronized(object){....} 它可以获得对象的少数几个指令的独占访问权,在程序中使用同步机制时有一个原则:就是不要在synchronized方法中花费大量的时间。如果本程序使用了同步方法的话,无疑会违背这一原则(虽然也可运行,但效率不高),因此在程序中当需要对一些变量进行操作时,使用了同步块。一般系统编程人员比较可能使用同步块以提高程序运行效率,see了,老外做东西是TMD得想得多了一点。OK。下面看看程序中的代码的几个同步块: 1。 synchronized (myWorm) {//不是在B的run()方法中,它是主线程A的操作 if (audioPlayer != null) { audioPlayer.close(); audioPlayer = null; } if (tonePlayer != null) { tonePlayer.close(); tonePlayer = null; }//主线程A取得了对象myWorm的锁,并取得了块中的代码的独占访问权(即是其中 几个变量的访问权),这样可以与主线程A互斥的设置这几个变量。 myWorm.notifyAll();//当设置结束后释放该锁,通知所有在等待列表中的线程(这里只有线程B)可以访问该资源了,B线程会从程序中的wait()方法后继续运行。 } 2。 synchronized (myWorm) { gameDestroyed = true; myWorm.notifyAll();//同上 } 3。 synchronized (myWorm) { if (gameOver) { if (WormScore.getHighScore(level) < score) { /* Display score screen */ WormScore.setHighScore(level, score, "me"); } if ((audioPlayer != null) && (audioPlayer.getState() == Player.STARTED)) { try { audioPlayer.stop(); Manager.playTone(60, 400, 100); } catch (Exception ex) { } } repaint(); // serviceRepaints(); // Draw immediately myWorm.wait();// 挂起线程B等待主线程A的操作,这里是等待用户的键盘事件 //当主线程A运行到上面的notifyAll()方法后,说明键盘事件结束, //主线程A已经对一些变量进行了同步的设置,这时线程B继续从这里运行 } else if (gamePaused) { repaint(); // serviceRepaints(); // Draw immediately myWorm.wait();//同上 } 完!不知道你还有什么问题?大家一同商量,如有错误请高手多多指教!!! 不好意思错了,上面第一个注释应该是//主线程A取得了对象myWorm的锁,并取得了块中的代码的独占访问 权(即是其中 几个变量的访问权),这样可以与"线程B"互斥的设置这几个变量。在请问楼上的可否把你的Worm程序法一份给我。[email protected],谢了 谢谢楼上的,不过我觉得repaint方法里肯定还包括一个线程的,你认为呢? 经过一段时间学习j2me,除了类库受限外,我还觉得midlet和application之间的差别主要表现在对程序的控制上,一个application的控制权完全在于程序员本身,但是,我觉得自己写的midlet程序是不能叫做完整的程序的,因为JAMS(Java Application Management System)也是控制midlet的极为重要的角色,这个角色甚至比你自己还要重要。我认为,当一个midlet启动的时候,必然有一个优先级较高的线程跟随着该midlet启动,其主要任务是监听键盘输入,当然,就像楼上所说,这个线程就是主线程。除过主线程之外,JAMS应该还有一个机制来监听midlet的状态的转变,当你调用destroyApp(false);noticeDestroyed();时,这个机制就将当前状态转变为销毁态,当你调用pauseApp();noticePause();时,这个机制就将当前状态转变为暂停态。notice方法正是这个机制和midlet的通信接口!当然,这个机制也可以是主线程。上面所说的两点,其内容都由JAMS来做,所以说,midlet不完全控制在程序员的手中。 我对j2me不是很了解,但是我觉得midlet有点像java applet,也有一个init,start,stop的过程,但这些是由系统或者说虚拟机控制的,其实你一样可以很好的控制程序,只不过要多考虑一些问题而已。放暑假也没回家,正好没事一个人在实验室又写了个贪吃蛇(applet的),不过还有点问题,搞好了我会把它贴出来。 to:gyf168(下蛋的猴子)这是我昨天写的一篇文档,咱们讨论讨论:==============================================================================标题:敲开MIDlet的脑壳----在MIDlet中另外运行的两个线程作者:qlampskyface先定义几个名词:1.MyMIDlet是继承了MIDlet的类(至于MyMIDlet是否实现其它接口,我们不去关心)2.MyCanvas是继承了Canvas的类(MyCanvas是否实现其它接口,我们也不去关心)3.“进入”表示跟进debug的路线第一个“另外”: 经过debug,我发现,在主线程中,一个midlet中最先被执行的代码是MyMIDlet类的对象的构造函数,而后进入了java.lang.Class类(public final)的runCustomCode()方法(static),而后再进入com.sun.midp.midlet.MIDletState类(public abstract)中未知方法(调试看不出来,如有人知道请告知),而后再进入com.sun.midp.midlet.Selector类(extends MIDlet implements CommandListener, Runnable)中,启动了run()方法,第一个“另外”诞生了。第二个“另外”: 接着上面继续debug: 下来才是调用MyMIDlet类实例的startApp方法,执行Display.getDisplay(this).setCurrent(Displayable),由于setCurrent的参数是MyCanvas类的实例,所以,这一执行(指Display.getDisplay(this).setCurrent(Displayable))即调用(进入)了MyCanvas的paint()方法,所以,Display的成员方法setCurrent应该类似于下面的代码:public void setCurrent(Displayable d){ ... ... Graphics g = d.getGraphics();//生成Graphics实例 d.paint(g); ... ...}在执行完paint方法之后,进入了Canvas类中的其它未知方法,而后再进入Display的未知方法,而后进入几个无关类之后就断掉了,原因无从查找,不过我们可以这样得到第二个另外:在模拟器单击开始,你会发现又能debug了,这时,当你执行完commandAction方法后,再debug几次,你就进入了这么一个类:com.sun.midp.lcdui.DefaultEventHandler(public & implements EventHandler),而后进入com.sun.midp.lcdui.AutomatedEventHandler(public & extends DefaultEventHandler implements AutomationHandler)类,这两个类成继承关系,而在DefaultEventHandler类中又有一个内部类VMEventHandler(implements Runnable)实现了run()方法,所以,第二个“另外”产生了:)关于第一个“另外”:我认为这个线程是监听midlet状态的监听线程,叫状态监听线程关于第二个“另外”:我认为是监听键盘输入的监听线程,叫键盘监听线程所以,在一个midlet中,一般有下面这四个线程:1.主线程2.状态监听线程3.键盘监听线程4.自己实现的画动画的线程。关于自己程序中画动画的线程(该线程中实现了对动画的repaint):该线程在上述步骤中已经启动,启动的地方通常有两个,一处是在MIDlet对象的构造过程中(如果有和该对象成聚合关系的其它对象,则也在这里初始化);另外一处则在startApp()方法中,在实现了Display.getDisplay(this).setCurrent(Displayable);语句之后。=======================================================================在上面的debug过程中,我使用的是sun自己的wtk2.1,别的api的debug过程可能不一样,但是这是大同小异的,你可以触类旁通。比如西门子的api中监听键盘线程在javax.microedition.lcdui.EventQueue(final & implements Runnable)中实现. 数姐越界 用java能否写出来一个音乐播放器? 说一个有趣的故事,再大家告诉我:工厂模式,是不是有三种:工厂方法、抽象工厂、工厂 ?? 我脑袋快炸掉了 jTextPane设置为text/html后,我直接将WORD中的文档复制进去,无法成功,怎么办? 请教//和\\的区别 关于动画的问题 一个很菜的文件传输问题 搞了几年windows下的vc++与delphi开发,以后想去上海发展,想学再学点java或linux开发,想请那位高人指点一下应学那方面?其他也行. 如何在JAVA中向已经存在的excel中写入内容? 望兄弟们指点指点Java背台程序的运行 请教一个引用自定义包的问题:
你好,代码我看了一下,虽然我对j2me的midlet不太了解,但我认为此程序只有两个线程:main主线程-A和wormpit中的线程--B,主线程负责监听键盘事件,而线程B负责对界面进行重绘操作,因此程序中有很多的wait,notifyall,以及synchronized,下面我来解释一下为什么?
由于线程A,B都会对一些变量进行访问如:gameOver,gamePaused,audioPlayer等,因此需要对他们进行同步的访问。 首先,程序出现了很多的同步块:而没有使用synchronized方法
其格式为:synchronized(object){....}
它可以获得对象的少数几个指令的独占访问权,在程序中使用同步机制时有一个原则:就是不要在synchronized方法中花费大量的时间。如果本程序使用了同步方法的话,无疑会违背这一原则(虽然也可运行,但效率不高),因此在程序中当需要对一些变量进行操作时,使用了同步块。一般系统编程人员比较可能使用同步块以提高程序运行效率,see了,老外做东西是TMD得想得多了一点。
OK。下面看看程序中的代码的几个同步块:
1。 synchronized (myWorm) {//不是在B的run()方法中,它是主线程A的操作
if (audioPlayer != null) {
audioPlayer.close();
audioPlayer = null;
}
if (tonePlayer != null) {
tonePlayer.close();
tonePlayer = null;
}//主线程A取得了对象myWorm的锁,并取得了块中的代码的独占访问权(即是其中 几个变量的访问权),这样可以与主线程A互斥的设置这几个变量。
myWorm.notifyAll();//当设置结束后释放该锁,通知所有在等待列表中的线程(这里只有线程B)可以访问该资源了,B线程会从程序中的wait()方法后继续运行。
} 2。 synchronized (myWorm) {
gameDestroyed = true;
myWorm.notifyAll();//同上
}
3。 synchronized (myWorm) {
if (gameOver) {
if (WormScore.getHighScore(level) < score) {
/* Display score screen */
WormScore.setHighScore(level, score, "me");
}
if ((audioPlayer != null) &&
(audioPlayer.getState() == Player.STARTED)) {
try {
audioPlayer.stop();
Manager.playTone(60, 400, 100);
} catch (Exception ex) { }
}
repaint();
// serviceRepaints(); // Draw immediately
myWorm.wait();// 挂起线程B等待主线程A的操作,这里是等待用户的键盘事件
//当主线程A运行到上面的notifyAll()方法后,说明键盘事件结束,
//主线程A已经对一些变量进行了同步的设置,这时线程B继续从这里运行
} else if (gamePaused) {
repaint();
// serviceRepaints(); // Draw immediately
myWorm.wait();//同上
}
完!不知道你还有什么问题?大家一同商量,如有错误请高手多多指教!!!
,上面第一个注释应该是//主线程A取得了对象myWorm的锁,并取得了块中的代码的独占访问 权(即是其中 几个变量的访问权),这样可以与"线程B"互斥的设置这几个变量。在请问楼上的可否把你的Worm程序法一份给我。[email protected],谢了
主要表现在对程序的控制上,一个application的控制权完全在于程序员本身,但是,
我觉得自己写的midlet程序是不能叫做完整的程序的,因为JAMS(Java Application Management System)也是控制midlet的极为重要的角色,这个角色甚至比你自己还要重要。我认为,当一个midlet启动的时候,必然有一个优先级较高的线程跟随着该midlet启动,
其主要任务是监听键盘输入,当然,就像楼上所说,这个线程就是主线程。除过主线程之外,JAMS应该还有一个机制来监听midlet的状态的转变,当你调用destroyApp(false);noticeDestroyed();时,这个机制就将当前状态转变为销毁态,当你调用pauseApp();noticePause();时,这个机制就将当前状态转变为暂停态。notice方法正是这个机制和midlet的通信接口!当然,这个机制也可以是主线程。上面所说的两点,其内容都由JAMS来做,所以说,midlet不完全控制在程序员的手中。
标题:敲开MIDlet的脑壳----在MIDlet中另外运行的两个线程
作者:qlampskyface先定义几个名词:
1.MyMIDlet是继承了MIDlet的类(至于MyMIDlet是否实现其它接口,我们不去关心)
2.MyCanvas是继承了Canvas的类(MyCanvas是否实现其它接口,我们也不去关心)
3.“进入”表示跟进debug的路线
第一个“另外”:
经过debug,我发现,在主线程中,一个midlet中最先被执行的代码是MyMIDlet类的对象的构造函数,而后进入了java.lang.Class类(public final)的runCustomCode()方法(static),而后再进入com.sun.midp.midlet.MIDletState类(public abstract)中未知方法(调试看不出来,如有人知道请告知),而后再进入com.sun.midp.midlet.Selector类(extends MIDlet implements CommandListener, Runnable)中,启动了run()方法,第一个“另外”诞生了。第二个“另外”:
接着上面继续debug:
下来才是调用MyMIDlet类实例的startApp方法,执行
Display.getDisplay(this).setCurrent(Displayable),由于setCurrent的参数是MyCanvas类的实例,所以,这一执行(指Display.getDisplay(this).setCurrent(Displayable))即调用(进入)了MyCanvas的paint()方法,所以,Display的成员方法setCurrent应该类似于下面的代码:
public void setCurrent(Displayable d){
... ...
Graphics g = d.getGraphics();//生成Graphics实例
d.paint(g);
... ...
}在执行完paint方法之后,进入了Canvas类中的其它未知方法,而后再进入Display的未知方法,而后进入几个无关类之后就断掉了,原因无从查找,不过我们可以这样得到第二个另外:
在模拟器单击开始,你会发现又能debug了,这时,当你执行完commandAction方法后,再debug几次,你就进入了这么一个类:com.sun.midp.lcdui.DefaultEventHandler(public & implements EventHandler),而后进入com.sun.midp.lcdui.AutomatedEventHandler(public & extends DefaultEventHandler implements AutomationHandler)类,这两个类成继承关系,而在DefaultEventHandler类中又有一个内部类VMEventHandler(implements Runnable)实现了run()方法,所以,第二个“另外”产生了:)关于第一个“另外”:我认为这个线程是监听midlet状态的监听线程,叫状态监听线程关于第二个“另外”:我认为是监听键盘输入的监听线程,叫键盘监听线程所以,在一个midlet中,一般有下面这四个线程:1.主线程2.状态监听线程3.键盘监听线程4.自己实现的画动画的线程。关于自己程序中画动画的线程(该线程中实现了对动画的repaint):
该线程在上述步骤中已经启动,启动的地方通常有两个,一处是在MIDlet对象的构造过程中(如果有和该对象成聚合关系的其它对象,则也在这里初始化);另外一处则在startApp()方法中,在实现了Display.getDisplay(this).setCurrent(Displayable);语句之后。
=======================================================================
在上面的debug过程中,我使用的是sun自己的wtk2.1,别的api的debug过程可能不一样,但是这是大同小异的,你可以触类旁通。
比如西门子的api中监听键盘线程在javax.microedition.lcdui.EventQueue(final & implements Runnable)中实现.