关于Android系统休眠后,线程的执行情况
2016-04-22 14:56
531 查看
理论上,android系统休眠后,app进程会被挂起,所以相关的执行线程也会被挂起,那些java线程的操作例如:wait,await,sleep,循环阻塞,handler的delay,线程池的delay操作都会被挂起,因为它们使用的系统计时器在休眠的时候是停止的,例如:SystemClock.uptimeMillis(),其实针对不同版本的android系统这些表现各有不同,有些android系统是休眠后这些计时变慢了,原先计时5秒的,休眠后可能要计时5到6分钟,在android系统中AlarmManager可以解决上述问题,闹钟在系统休眠的时候也会唤醒系统的,闹钟使用的计时器在休眠的时候是继续跑的,例如:SystemClock.elapsedRealtime(),但是闹钟的计时并不是很准确,甚至有秒级别的误差:
1. setRepeating方法是重复的唤醒操作,根据api文档可知系统会对这些做优化,唤醒时间并不会严格的按照你设置的参数时间来执行
2. set方法在sdk版本低于19的实现是严格准确的按照设置的时间唤醒的,但是在sdk版本高于或者等于19的实现是经过优化的,并不会准确按照设置的时间唤醒,所谓的优化就是系统有可能判断到间隔时间很小的有两个闹钟唤醒操作,这时候系统可能就会自动的把比较早的那个闹钟唤醒操作和比较晚的唤醒操作合并为一个
3. 根据api文档说明,想要精确按照设置时间唤醒可采用setExact方法,但是据我真机(小米4C,6.0系统)实测,这个方法的唤醒任然存在较大误差,误差甚至到秒级别,有的会误差几秒钟,只能说基本准确
下面是测试代码:
补充一点:要把alarm和其他的定时测试分开执行,alarm唤醒之后会影响其他线程的测试的
上面除了alarm会按时唤醒执行,其他的在手机休眠后计时变慢了,休眠越久,误差时间就拉的越大,都是20秒的定时任务,休眠后,除了alarm,其他的误差慢慢变大,例如一开始是30秒,然后1分钟,3分钟,5分钟,10分钟,16分钟等等,但是这些计时延迟的时间都基本一直,说明除了alarm,其他使用的系统计时器都是一致的
1. setRepeating方法是重复的唤醒操作,根据api文档可知系统会对这些做优化,唤醒时间并不会严格的按照你设置的参数时间来执行
2. set方法在sdk版本低于19的实现是严格准确的按照设置的时间唤醒的,但是在sdk版本高于或者等于19的实现是经过优化的,并不会准确按照设置的时间唤醒,所谓的优化就是系统有可能判断到间隔时间很小的有两个闹钟唤醒操作,这时候系统可能就会自动的把比较早的那个闹钟唤醒操作和比较晚的唤醒操作合并为一个
3. 根据api文档说明,想要精确按照设置时间唤醒可采用setExact方法,但是据我真机(小米4C,6.0系统)实测,这个方法的唤醒任然存在较大误差,误差甚至到秒级别,有的会误差几秒钟,只能说基本准确
下面是测试代码:
补充一点:要把alarm和其他的定时测试分开执行,alarm唤醒之后会影响其他线程的测试的
public class MainActivity extends AppCompatActivity { ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); int i = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this, "sss", Toast.LENGTH_SHORT).show(); } }); scheduledExecutorService.scheduleWithFixedDelay(new Runnable() { @Override public void run() { String format = new SimpleDateFormat("HH:mm:ss").format(new Date()); NotificationUtil.showNotification(MainActivity.this, new Intent(), 100, "ScheduledExecutorService休眠测试", format + ":ScheduledExecutorService执行"); i++; } }, 20, 20, TimeUnit.SECONDS); new Thread() { @Override public void run() { long now; while (true) { now = SystemClock.elapsedRealtime(); while (SystemClock.elapsedRealtime() - now < 20000) ; String format = new SimpleDateFormat("HH:mm:ss").format(new Date()); NotificationUtil.showNotification(MainActivity.this, new Intent(), 101, "Thread休眠测试", format + ":Thread执行"); } } }.start(); new Thread() { @Override public void run() { while (true) { synchronized (this) { try { this.wait(20000); } catch (InterruptedException e) { e.printStackTrace(); } } String format = new SimpleDateFormat("HH:mm:ss").format(new Date()); NotificationUtil.showNotification(MainActivity.this, new Intent(), 102, "wait休眠测试", format + ":wait执行"); } } }.start(); Handler handler = new Handler() { @Override public void handleMessage(Message msg) { sendEmptyMessageDelayed(1, 20000); if (msg.what == 1) { String format = new SimpleDateFormat("HH:mm:ss").format(new Date()); NotificationUtil.showNotification(MainActivity.this, new Intent(), 103, "handler休眠测试", format + ":handler执行"); } } }; handler.sendEmptyMessageDelayed(1, 20000); new Thread(){ @Override public void run() { while (true) { try { sleep(20000); } catch (InterruptedException e) { e.printStackTrace(); } String format = new SimpleDateFormat("HH:mm:ss").format(new Date()); NotificationUtil.showNotification(MainActivity.this, new Intent(), 104, "sleep休眠测试", format + ":sleep执行"); } } }.start(); startService(new Intent(this, TestService.class)); } } public class TestService extends Service { ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); HandlerThread handlerThread = new HandlerThread("ht"); handlerThread.start(); Handler handler = new Handler(handlerThread.getLooper()); handler.post(new Runnable() { @Override public void run() { while (true) { try { Thread.sleep(20000); } catch (InterruptedException e) { e.printStackTrace(); } scheduledExecutorService.schedule(new Runnable() { @Override public void run() { String format = new SimpleDateFormat("HH:mm:ss").format(new Date()); NotificationUtil.showNotification(TestService.this, new Intent(), 105, "Service休眠测试", format + ":Service执行"); } }, 0, TimeUnit.SECONDS); } } }); Intent intent = new Intent(this, InnerGuardReceiver.class); intent.setAction("com.xtc.watch.guard.push"); PendingIntent pendingIntent = PendingIntent.getBroadcast(this, -1001, intent, 0); AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); alarmManager.cancel(pendingIntent); alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 20000, 20000, pendingIntent); } @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } public static class InnerGuardReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String format = new SimpleDateFormat("HH:mm:ss").format(new Date()); NotificationUtil.showNotification(context, new Intent(), 106, "alarm休眠测试", format + ":alarm执行"); } } }
上面除了alarm会按时唤醒执行,其他的在手机休眠后计时变慢了,休眠越久,误差时间就拉的越大,都是20秒的定时任务,休眠后,除了alarm,其他的误差慢慢变大,例如一开始是30秒,然后1分钟,3分钟,5分钟,10分钟,16分钟等等,但是这些计时延迟的时间都基本一直,说明除了alarm,其他使用的系统计时器都是一致的
相关文章推荐
- xmarin.android for vs2015使用百度地图api3.6.1
- android项目中,测试Socket连接时遇到的问题
- android学习之SimpleAdapter
- Android组件标识符
- Android ProGuard 基础学习。
- Android ViewAnimation 使用详解
- android基础知识-Vibrator(振动器) 使用
- Java Future Pattern和Android AsyncTask
- Android Property Animation
- android DecimalFormat使用,保留小数点后x位
- Android 二维码扫描框 加四个角及中间横线自动下滑
- android 百度地图定位开发2
- android 百度地图定位开发1
- Android PullToRefresh (ListView GridView 下拉刷新) 使用详解
- Android 4.4 Graphic系统详解(2) VSYNC的生成
- Android之自定义生成彩色二维码
- Android内存管理机制
- Android Vibrator的使用
- Android API,版本对照
- Android程序框架设计思想01