在Java中,Annotation(注解)是一种可添加到源码中的句法元数据(Java annotation),类、方法、变量、参数以及包都可以进行注解。
注解主要有如下几个用途:
- 为编译器提供信息: 编译器使用annotation来检测错误或者消除警告;
- 编译或者部署时处理: 可以利用注解信息产生代码,XML文件等;
- 运行时处理: 可在运行时检查注解,产生相应的代码;
在Java中,Annotation(注解)是一种可添加到源码中的句法元数据(Java annotation),类、方法、变量、参数以及包都可以进行注解。
注解主要有如下几个用途:
在Android开发调试过程中,常需要使用ps
指令用于获取当前系统进程的快照信息(如果想要获取进程动态信息,则需要使用top
命令)。通过ADB SHELL连接上手机后,输入adb shell
命令进入shell控制台, 输入ps
即可查看当前系统所有进程信息:
HTTP(Hypertext Transfer Protocol)即超文本传输协议,是一种用于传输文本、音视频等超媒体(hypermedia)的应用层协议。HTTP从1990年开始就应用于WWW(World Wide Web)服务中,其发展变化与WEB服务紧密相连。这篇文章,就来看看HTTP协议的基本概念。
HTTP协议允许不同类型的客户端与服务端进行通讯,支持不同的网络配置,并不依赖于特定的系统。在消息交换过程中,不保存任何状态(state-less,状态无关)。HTTP协议请求基于Request/Response,一个客户端向服务端发送request,该请求包含了Request Method, URL,协议版本以及请求的资源类型;服务端得到请求后,返回一个response,包括状态信息(协议版本,状态码)以及请求的资源。这样一次Request/Response的过程我们称为一次HTTP会话(session),大致有三个阶段:
哈希函数(hash function)是一个将某个集合内的元素映射到一个大小固定的元素集合的函数,其在数据查找、数据去重等方面有着许多的应用。这里,就来看看常用的一些哈希函数是如何来实现的。
最简单的一种Hash函数实现方法,来自于Rober Sedgwicks的C语言算法书:
1 |
|
缓存(Memory Cache)在一般意义上是指一种用于存储当前或者历史数据的硬件或者软件结构,其目的是加速数据的存取,提升系统效率。目前大多数的计算机系统都会在软件或者硬件层面集成有各种cache, 比如:
一般来说, 现代的多核CPU系统都有多级的缓存结构, 简图如下:
这篇文章将要讨论的cache是指CPU与主内存之间的一种基于SRAM(Static Random Access Memory)存储结构。
自计算机诞生以来,CPU的性能大致都按照摩尔定律以每年50%的速度递增,而主内存RAM(Random Access Memory)的性能增速却只有7%,因此在CPU性能与主内存性能之间渐渐形成了一个鸿沟:
之前的一篇文章,讲到了应用程序无响应(ANR)时Android的处理逻辑。这篇文章,就来分析下应用进程发生崩溃(Crash)时,Android是如何处理的?总的说来,Android主要有两大类Crash:
Activity是Android负责与用户交互的实体。一个应用一般由多个Activity组成;一个Activity不仅可以打开应用内的Activity,也可以打开其他应用内的Activity,比如通过一个名为android.intent.action.VIEW
的Intent事件可以打开浏览器;通过android.intent.action.DIAL
可以向CALL发送拨号请求。一系列的Activity组合在一起(完成某个特定的“任务“)构成了一个任务(一个后进先出的队列,被称为back stack),而多个任务又构成了一个任务栈(后台可以有多个任务栈,但系统如需恢复内存,则会杀死部分应用,清空部分任务,以释放内存,因此长时间后应用状态会丢失)。以下图为例,图中的back stack一开始只有一个Activity1;接着在Activity1中启动Activity2,此时Activity2位于队列的顶部,而Activity1位于栈底(Activity1处于Stop状态),而Activity2又启动一个Activity3,同样,Activity3压入栈顶。如果此时通过回退键(Back)用户离开Activity3,则Activity3从栈中清除,被系统销毁,而Activity2则恢复到可见状态(resume)。
ANR即Application Not Responding, 应用无响应:当应用在某一个时间内无法及时响应用户请求时,系统会弹出一个对话框,告知用户应用无法响应。此时,用户可以选择关闭应用。对于Android应用来说,有一个UI线程(主线程)专门负责与用户交互,如果在此线程中进行耗时的操作,比如读取磁盘数据、从网络下载资源等IO操作,通常会导致UI线程阻塞,从而无法及时处理用户的输入请求,发生ANR。
Android是通过AMS跟WMS来监控应用响应状态的,一般有如下两种ANR情况:
对于输入无响应的情况,native监控到输入无响应时,则告知WMS,最后由WMS发送消息告诉AMS,某个应用发送了ANR,最后AMS会弹出Application Not Responding的对话框,请求用户关闭应用;对于广播无响应的情况是由AMS负责处理的,AMS对于每个发送出去给广播接收者的广播都有一个10s的定时,如果广播接收者在10s内尚未处理完,则视为无响应,因此也会弹出Application Not Responding。
Java语言synchronized
关键字自带了一个内置的隐性锁(implicit lock),使用起来方便简单,但是内置锁一旦使用,则会强制将某个代码块加锁或者解锁,而且内置锁并不支持可中断的获取锁。从Java5.0开始,提供了一个并发工具包java.util.concurrent.*
,实现了显性锁(explicit lock)ReentrantLock
(可重入锁,可多次获取同一个锁);ReentrantLock
实现了与synchronized
一样的功能,确保并发过程中数据的互斥访问与可见性。获取ReentrantLock
相当于进入一个synchronized
代码块,而释放ReentrantLock
则相当于从一个synchronized
代码块退出。ReentrantLock
实现了如下Lock.java
接口:
1 |
|
在古希腊时代,哲学家Democritus(德谟克利特)提出了关于物质构成的理论:所有物质都由不可分割的元素组成,这种元素被称之为原子(atom)。编程中所说的原子性(atomic)借用了这个概念, 用于表示某个代码指令动作的不可中断性。在之前的一篇文章(Java Memory Model)时,提到多线程并发访问共享数据时,会出现数据竞争,从而导致数据不一致的情况。比如对一个整型变量进行加一的操作: ++counter
,表面上看,这是一个单一原子操作,但实际上这个操作有三个步骤:首先,需要从内存中(有可能是cache中)加载到寄存器;接着,将该值加一;最后需要将寄存器中的值写入内存。这样,在多个线程访问的情况,上述几个步骤出现交织执行,就可能出现各个线程读写数据不一致的情形。
Atomic Theory: http://www.softschools.com/timelines/atomic_theory_timeline/95/
于是,有了原子操作。原子操作确保了执行的不可中断,因而能避免数据冲突。Java从5.0开始有一个atomic
的工具包专门支持int
,long
以及引用变量的原子操作,而在硬件层面,目前大部分处理器都支持诸如CAS
(CompareAndSet/CompareAndSwap),FAA
(FetchAndAdd)等原子指令。在介绍Java中的原子操作类之前,先来了解下硬件层面的原子指令。