请教高手,多线程的难题

jiangnancaizi 2009-07-17 10:13:14
以下代码是为了在代码中实现repeat键的(比如按1键,就会不断地打出1直到释放键, 下面的down指得是按下键事件,release 指得是释放键盘)


if (event.getAction() == MotionEvent.ACTION_DOWN) {
keyevent = new KeyEvent(KeyEvent.ACTION_DOWN, keycode);

if((keycode >= keyevent.KEYCODE_0) && (keycode <= keyevent.KEYCODE_9)){
new Thread(){ //这个线程就是实现repeat的主要代码,相当于每次按下键都启动一个线程
public void run() {
int sleepTime = 800; // repeat的初始时间,就是说按下去800毫秒后才第一次repeat
while(true){
try {
sleep(sleepTime);
}catch (InterruptedException e) {
Log("test InterruptedException "); // 看看是否被中断
}
int action = keyevent.getAction();
if (action == MotionEvent.ACTION_UP){ //释放键的时候返回
return;
}

mHandler.SentMessage(发送一次虚拟down出去);
sleepTime = 200; // repeat间隔时间,就是第一次repeat开始后每隔这么久发一次虚拟down
}
}
}.start();
}
} else if (event.getAction() == MotionEvent.ACTION_UP) {
keyevent = new KeyEvent(KeyEvent.ACTION_UP, keycode); //release事件发生
}

if (keyevent != null && (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_UP)){
mHandler.SentMessage(第一次down和最后的release事件都从这里发出);
}


用以上代码,我输入字符,大部分都是正常,但是有时候输入一个键(比如1)会同时输出2个1出来,通过打日志,发现第一个sleep(sleepTime)好像根本没起作用,据说sleep会被其他线程中断,但是此时Log("test InterruptedException ") 却没有打出来啊,我甚至试着把整个Thread 用synchronized(this){}包起来,还是没用啊。
就是说出现我所说的错误的时候(按下一个键很快会输出1个以上字符), 好像根本没经过第一个sleep(sleepTime)一样,哪怕我把
int sleepTime = 800改成int sleepTime = 8000都一样
...全文
140 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
jiangnancaizi 2009-07-20
  • 打赏
  • 举报
回复
谢谢楼上各位特别是
redduke1202的回答,
不过我把真个Thread用synchronized(this){new Thread(){}.start()}这样包起来,为啥还是无法解决问题啊,这样不就保证了线程的代码是同步的么
Sodino 2009-07-20
  • 打赏
  • 举报
回复
需要完整的代码来调试一下。并附上你的所想要的实现功能及操作步骤。


我也没看明白,实在地说,文字太多,代码又没有格式一下。
lijian_123 2009-07-20
  • 打赏
  • 举报
回复
线程太多影响性能啊!!!!,这是手机应用程序,CPU工作频率不太高!!!!
「已注销」 2009-07-20
  • 打赏
  • 举报
回复
//当前时间大于发生repeat事件的时间时,发生repeat事件
「已注销」 2009-07-20
  • 打赏
  • 举报
回复
int lastKeyPressed;
long keyRepeatTime;

void keyPressed(int keyCode)
{
lastKeyPressed = keyCode;//记录键值
keyRepeatTime = System.currentTimeMillis() + 800;//记录未来发生repeat事件的时间
}

void keyReleased(int keyCode)
{
keyRepeatTime = 0;//清除repeat事件
}

void run()
{
while(true)
{
//当前时间小于发生repeat事件的时间时,发生repeat事件
if(keyRepeatTime != 0 && System.currentTimeMillis() >= keyRepeatTime)
{
keyRepeatTime += 200;//计算下一次发生repeat事件的时间
//处理Repeat事件
}

Thread.sleep(50);
}
{
yangc_83 2009-07-20
  • 打赏
  • 举报
回复
感觉这种情况用线程太奢侈了
做个变量int i=0;//0的时候不画,1的时候画1111,2的时候画2222222...
在down的时候,将i设为1
在release 的时候,将i设为0
在PAINT中或你需要监听的地方画出来,不就OK了?
yangc_83 2009-07-20
  • 打赏
  • 举报
回复
感觉这种情况用线程太奢侈了
做个变量int i=0;//0的时候不画,1的时候画1111,2的时候画2222222...
在down的时候,将i设为1
在release 的时候,将i设为0
在PAINT中或你需要监听的地方画出来,不就OK了?
jiangnancaizi 2009-07-20
  • 打赏
  • 举报
回复
求解决办法啊
jiangnancaizi 2009-07-20
  • 打赏
  • 举报
回复
顶^_^。。。。。。。。
为国而战 2009-07-19
  • 打赏
  • 举报
回复
没有启动?
阿士匹灵 2009-07-18
  • 打赏
  • 举报
回复
期待高手
「已注销」 2009-07-18
  • 打赏
  • 举报
回复
线程太多,你每次按一个新的按键,都是产生一个线程出来,效率估计非常惊人,也带来了你上面所谓的Bug

假设先按下2,产生down事件,并启动一个线程(姑且称为线程2),线程开始休眠
松开按键2.产生up事件,线程2还在休眠
按下按键1,产生down事件,并启动线程1,线程1开始休眠
线程2休眠800ms完成,判断keyevent此时仍旧是down状态,发出虚拟down事件,但是键值是后来按下的1,于是楼主斯巴达了.

不管你休眠多少,前面的某个线程在后来休眠完成后都可能会影响后面的某次按键。如果你按键间隔正好小于此休眠时间的话

ps:J2me不推荐使用太多的线程,ui线程+联网线程足够了.判断repeat可以在ui线程里统一判断,即使要开线程,也只开一个线程就够了.从逻辑上来讲,如果后面有按键并启动了repeat检测线程,前面的线程应该已经废了,如果还继续运行,那就是逻辑Bug了
xuyan87101 2009-07-17
  • 打赏
  • 举报
回复
学习,帮顶……
kf156 2009-07-17
  • 打赏
  • 举报
回复
你这方法是写在哪的?
怀疑是keyPressed与此方法的线程是个异步的过程导致的
按键按下,keyevent 为按下,线程启动输出
由于是异步过程按键放开时,keyevent 可能还未没被赋值
而此时第二个键又被按下, keyevent 还是被赋于按下的状态
上一次的线程未被结束,还依旧在执行输出

wormwormwormworm 2009-07-17
  • 打赏
  • 举报
回复
up
快乐的2 2009-07-17
  • 打赏
  • 举报
回复
看不懂,是不是线程sleep的时候产生的事件获取有延迟啊?先sleep了800MS,获取Action-UP时候没有获得,其实这里已经产生了UP事件,但是线程没有捕获到。
是不是应该在内的循环条件的true值用一个变量来控制,只要有UP事件产生就将其改为FALSE,而down事件产生的时候则赋值为true。

13,100

社区成员

发帖
与我相关
我的任务
社区描述
Java J2ME
社区管理员
  • J2ME社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧