安全循环每秒运行一次

时间:2014-07-28 13:45:23

标签: java android

所以我想要一个每秒运行一次的while循环,但显然使用Thread.sleep(1000);,不起作用,因为它会使应用程序冻结并因此错误而崩溃:

07-28 15:03:17.641: A/libc(5792): Fatal signal 6 (SIGABRT) at 0x00000280 (code=0), thread 5792 ()

所以我猜测循环即时使用不够安全并且使用了太多资源 循环在服务中运行,并由actionbutton:)

初始化
while(buttonpressed != false);
        try {
            writer = new FileWriter(timedata);
                   writer.append(TIME);

                    writer.flush();
                    writer.close();   
                    Thread.sleep(1000);
        }       

3 个答案:

答案 0 :(得分:2)

请改用AlarmManager

注册您的服务以每秒(从this question)运行所述操作:

  Intent myIntent = new Intent(context, MyServiceReceiver.class);
  PendingIntent pendingIntent = PendingIntent.getBroadcast(context,  0, myIntent, 0);

  AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
  Calendar calendar = Calendar.getInstance();
  calendar.setTimeInMillis(System.currentTimeMillis());
  calendar.add(Calendar.SECOND, 1); // first time
  alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 1000, pendingIntent);

您尝试做的是在UI线程上调用sleep(1000)(负责更新面向用户的UI更改的线程)。这对Android来说是一个很大的禁忌,因为它会让你的应用看起来没有反应。

在用户评论后编辑澄清:

我不知道您如何设置buttonpressed,但您可能想要使用OnTouchListener

boolean shouldBeDoingThings = true;
writer = new FileWriter(timedata);
Button.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if(event.getAction() == MotionEvent.ACTION_DOWN){
            shouldBeDoingThings = true;
            return true;
        }
        else  if(event.getAction() == MotionEvent.ACTION_UP){
            shouldBeDoingThings = false;
            return true;
        }
        return false;
    }
});

然后使用消息或意图启动流程(AlarmReceiver向您的服务发送消息以将shouldBeDoingThings设置为true)。

之后,在您服务的某个地方,您可以运行:

class Task implements Runnable {

        private long lastUpdatedTime;

        public Task()
        {
                 lastUpdatedTime = 0;
        }

        @Override
        public void run() {
                if(shouldBeDoingThings)
                {
                    if(TIME - lastUpdatedTime > 1000)
                    {
                        writer.append(TIME);
                        writer.flush();
                        lastUpdatedTime = TIME;
                    }
                }
            }
        }
    }

总而言之,永远记住:从不阻止UI线程。这适用于当今的大多数移动SDK。

希望我能为你解决问题。

答案 1 :(得分:0)

使用这个简单的旋转循环,

long now = System.currentMillisec();
while(now < expectedElapsedTime){ now = System.currentMillisec(); }

你不会有准确的类型暂停,因为在线程休眠和唤醒后,它将被安排到CPU调度,然后它可能不会完全是10秒(如果那是你的时间希望它停止。)

答案 2 :(得分:0)

我没有其他代码可以使用,但我设法编写了一段代码,可以执行您想要的操作:您可以更改我添加的打印语句以及要包含的内容。我认为你缺少的是while循环中的catch语句。

public class StackOverflow 
{
    static boolean buttonpressed = true;
    public static void main(String[] args)
    {
    while(buttonpressed != false)
    {
    try 
    {
     System.out.println("hi");
        Thread.sleep(1000);
    }
    catch (Exception e)
    {

    }
    }
    }
}