java.text.format

本文详细介绍了Java中数字格式化(DecimalFormat)、日期格式化(simpleDateFormat)和文本替换格式化(MessageFormat)的使用方法,包括具体实例演示,并强调了在数据库中保存日期时应注意的事项。

oh ,now it's time to sum up the class of "java.text.format" , as i forget how to format a date after using other's tools .

1、数字格式化   DecimalFormat

使用 java.text.format  decimalFormat = new DecimalFormat("#.##"); 保留2位小数,允许整数与小数不存在。

使用 java.text.format decimalFormat = new DecimalFormat("0.0#");保留2位小数,无小数,小数位补0 。 无整数,整数位补0


2、日起格式化   simpleDateFormat

使用java.text.format dateFormat = new SimpleDateFormat(pattern) .

pattern : yyyy-MM-dd HH:mm:ss SSS E 表示 2014-12-06 23:59:58 333 星期四  and then ,you can short of the pattern just to suit yourself

注意 : 使用mysql格式化日起保存到数据库的时候,请不要用毫秒,否则会四舍五入,  2014-12-06 23:59:58 500 会保存为 2014-12-07 00:00:00


3、文本替换格式化 MessageFormat

描述:使用一个数组中的元素去替换String(模板)中{ArgumentIndex , FormatType , FormatStyle}中的指定位置

{ArgumentIndex , FormatType , FormatStyle} : {数组下标,格式化数组类型,格式}

例如 : String message = "xiao ming is {0} {1,number,#.##}" , Object  array = new Object[]{"high",3.33333} , String value = MessageFormat.format(message,array);

结果 : xiao ming is high 3.33 .   message就是模板。

then just thinking the result   if the message is "xiao ming is {} " . 是会全部打出呢 还是 说取消大括号 ?

建议使用:new MessageFormat(message).format(array);  因为上面的代码我无法得出正确结论 ,同时下面的代码就是上面代码的解析。。


for more message , just view  http://www.xuebuyuan.com/1576172.html 


anr问题trace如下: "main" prio=5 tid=1 Blocked | group="main" sCount=1 ucsCount=0 flags=1 obj=0x72df6468 self=0xb400007072878c00 | sysTid=3104 nice=-2 cgrp=ssfg sched=0/0 handle=0x71230e9d28 | state=S schedstat=( 273294290029 918944300434 897810 ) utm=18065 stm=9263 core=5 HZ=100 | stack=0x7fe106e000-0x7fe1070000 stackSize=8188KB | held mutexes= at com.android.server.alarm.AlarmManagerService$DeliveryTracker.onSendFinished(AlarmManagerService.java:5798) - waiting to lock <0x09677b19> (a java.lang.Object) held by thread 281 at android.app.PendingIntent$FinishedDispatcher.run(PendingIntent.java:382) at android.os.Handler.handleCallback(Handler.java:973) at android.os.Handler.dispatchMessage(Handler.java:100) at android.os.Looper.loopOnce(Looper.java:282) at android.os.Looper.loop(Looper.java:387) at com.android.server.SystemServer.run(SystemServer.java:1069) at com.android.server.SystemServer.main(SystemServer.java:677) at java.lang.reflect.Method.invoke(Native method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:600) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:983) DumpLatencyMs: 212.411 "binder:3104_E" prio=5 tid=281 Runnable | group="main" sCount=0 ucsCount=0 flags=0 obj=0x1770d568 self=0xb400006e2db00800 | sysTid=4606 nice=-2 cgrp=ssfg sched=1073741824/0 handle=0x6e0b1ab730 | state=R schedstat=( 113789554601 690500424244 405734 ) utm=6620 stm=4758 core=5 HZ=100 | stack=0x6e0b0b4000-0x6e0b0b6000 stackSize=989KB | held mutexes= "mutator lock"(shared held) at android.icu.util.Currency.getAvailableCurrencyCodes(Currency.java:200) at libcore.icu.ICU.getCurrencyCode(ICU.java:671) at java.util.Currency.getInstance(Currency.java:421) at java.text.DecimalFormatSymbols.initializeCurrency(DecimalFormatSymbols.java:933) at java.text.DecimalFormatSymbols.setCurrency(DecimalFormatSymbols.java:508) at java.text.DecimalFormatSymbols.fromIcuInstance(DecimalFormatSymbols.java:1085) at java.text.DecimalFormat.getDecimalFormatSymbols(DecimalFormat.java:2819) at java.text.SimpleDateFormat.zeroPaddingNumber(SimpleDateFormat.java:1678) at java.text.SimpleDateFormat.subFormat(SimpleDateFormat.java:1593) at java.text.SimpleDateFormat.format(SimpleDateFormat.java:1117) at java.text.SimpleDateFormat.format(SimpleDateFormat.java:1087) at java.text.DateFormat.format(DateFormat.java:333) at java.text.Format.format(Format.java:159) at com.android.server.alarm.AlarmManagerService.setImplLocked(AlarmManagerService.java:2473) at com.android.server.alarm.AlarmManagerService.setImpl(AlarmManagerService.java:2425) - locked <0x09677b19> (a java.lang.Object) at com.android.server.alarm.AlarmManagerService$4.set(AlarmManagerService.java:3103) at android.app.IAlarmManager$Stub.onTransact(IAlarmManager.java:198) at android.os.Binder.execTransactInternal(Binder.java:1523) at android.os.Binder.execTransact(Binder.java:1457) DumpLatencyMs: 84.4358这最后分析是什么结果呢
最新发布
08-20
<think>我们有两个线程的堆栈信息,一个是主线程(main)状态为Blocked,另一个是binder线程(binder:3104_E)状态为Runnable。 主线程(tid=1)被阻塞(Blocked)在AlarmManagerService$DeliveryTracker.onSendFinished方法上,因为它正在等待一个锁(<0x09677b19>),而这个锁被线程281(即binder:3104_E)持有。 而线程281(binder:3104_E)正在执行,并且它持有锁<0x09677b19>(在AlarmManagerService.setImplLocked方法中加锁)。该线程正在执行一些格式化操作(SimpleDateFormat.format),这可能会比较耗时。 分析: 1. 主线程阻塞是因为它需要获取锁<0x09677b19>,但该锁被binder线程持有。 2. binder线程正在执行AlarmManagerService.setImplLocked方法,并且在这个方法中进行了日期格式化操作(调用SimpleDateFormat.format),这个操作可能因为涉及ICU(International Components for Unicode)而较慢,尤其是在多线程环境下,因为SimpleDateFormat不是线程安全的,所以通常需要同步,但这里我们看到binder线程已经持有了锁(locked <0x09677b19>),所以其他线程(如主线程)想要获取同一个锁就必须等待。 问题:主线程被阻塞了212ms,如果这个阻塞时间超过5秒,就会导致ANR。虽然目前是212ms,但在高负载情况下,如果binder线程执行时间变长,可能会增加主线程阻塞时间,从而引发ANR。 建议: 1. 检查binder线程中执行的操作(特别是SimpleDateFormat.format)是否可以优化。例如,避免在锁内执行耗时操作(如格式化日期)。 2. 考虑使用线程安全的日期格式化类(如Java 8的DateTimeFormatter)或为每个线程创建独立的SimpleDateFormat实例(避免同步),从而减少锁持有时间。 3. 检查AlarmManagerService中锁的粒度,是否可以将耗时操作移出锁的范围。 结论:这是一个典型的锁竞争问题。主线程等待一个被binder线程持有的锁,而binder线程在锁内执行了相对耗时的操作,导致主线程阻塞。 注意:DumpLatencyMs表示从触发dump到完成dump的延迟,这里主线程的DumpLatencyMs为212ms,说明主线程已经被阻塞了至少212ms(因为dump时它还在阻塞)。而binder线程的DumpLatencyMs为84ms,说明它在dump时正在运行。 因此,需要优化binder线程中的耗时操作,减少锁持有时间,以避免主线程长时间阻塞。</think>### ANR问题分析结果 这段trace揭示了ANR(应用无响应)的核心原因:**主线程因锁竞争被阻塞,而关键锁被耗时Binder线程长期持有**。以下是详细分析: #### 1. **主线程阻塞原因**(`"main" prio=5 tid=1 Blocked`) - **阻塞位置**: `at com.android.server.alarm.AlarmManagerService$DeliveryTracker.onSendFinished(AlarmManagerService.java:5798)` - **关键问题**: `- waiting to lock <0x09677b19> (a java.lang.Object) held by thread 281` 主线程尝试获取锁`0x09677b19`失败,因该锁被线程281(Binder线程)持有。 - **阻塞时长**: `DumpLatencyMs: 212.411 ms`,已超过ANR敏感阈值(通常主线程阻塞>200ms需警惕)。 #### 2. **Binder线程问题**(`"binder:3104_E" prio=5 tid=281 Runnable`) - **持锁操作**: 在`AlarmManagerService.setImplLocked`中持有锁`<0x09677b19>`(`- locked <0x09677b19>`标识)。 - **耗时根源**: ```java at android.icu.util.Currency.getAvailableCurrencyCodes(Currency.java:200) // 调用ICU库 at java.text.SimpleDateFormat.format(SimpleDateFormat.java:1117) // 日期格式化 ``` **SimpleDateFormat.format** 因涉及ICU货币解析和线程不安全设计,成为性能瓶颈(耗时84ms)。 #### 3. ANR触发机制 | 环节 | 问题 | |---------------------|----------------------------------------------------------------------| | **锁竞争** | Binder线程持锁执行耗时格式化操作,主线程等待超时 | | **格式化性能瓶颈** | `SimpleDateFormat` 的ICU解析在并发场景效率低下 | | **系统服务设计** | `AlarmManagerService` 未隔离耗时操作,同步锁范围过大 | #### 4. 解决方案建议 - **紧急规避**: 替换`SimpleDateFormat`为线程安全的`DateTimeFormatter`(Java 8+)或`FastDateFormat`(Apache Commons)。 - **长期优化**: ```java // 示例:使用DateTimeFormatter替代SimpleDateFormat private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.systemDefault()); String formattedTime = formatter.format(Instant.now()); ``` - **架构改进**: 在`AlarmManagerService`中将日期格式化移出锁范围(`synchronized`块),或通过缓存预格式化结果减少调用。 ### 结论 ANR直接原因是**主线程等待锁超时**,根本症结在于Binder线程的`SimpleDateFormat`格式化操作效率低下。优化日期处理逻辑可解决问题。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值