具体介绍下TCP/IP:
TCP/IP一般指的是TCP/IP协议簇,主要包括了多个不同网络间实现信息传输涉及到的各种协议 主要包括以下几层:
应用层
:主要提供数据和服务。比如HTTP,FTP,DNS等。
传输层
:负责数据的组装、分块。比如TCP,UDP等。
网络层
:负责告诉通讯的目的地。比如IP等。
数据链路层
:负责连接网络的硬件部分,比如以太网,WIFI等。
HTTP的几种请求方法具体介绍
常见的有四种:
GET
获取资源,没有body,幂等性
POST
增加或者修改资源,有body
PUT
修改资源,有body,幂等性
DELETE
删除资源,幂等性
介绍几种启动模式。
standard
,默认模式,每次启动都会新建一个Activity实例,并进入当前任务栈
singleTop
,如果要启动的Activity在栈顶存在实例,则不会重新创建Activity,而是直接使用栈顶的Activity实例,并回调onNewIntent方法。
singleTask
,如果要启动的Activity在栈中存在实例,则不会重新创建Activity,而是直接使用栈里的Activity实例,并回调onNewIntent方法。并且会把这个实例放到栈顶,之前在这个Activity之上的都会被出栈销毁。
singleInstance
,有点单例的感觉,就是所启动的Activity会单独放在一个任务栈里,并且后续所有启动该Activity都会直接用这个实例,同样被重复调用的时候会调用并回调onNewIntent方法。
说说双重校验锁,以及volatile的作用
private volatile static Singleton mSingleton;
private Singleton() {
}
public Singleton getInstance() {
if (null == mSingleton) {
synchronized (Singleton.class) {
if (null == mSingleton) {
mSingleton = new Singleton();
}
}
}
return mSingleton;
}
}
为什么要加锁?
为什么不直接给getInstance方法加锁?
为什么需要双重判断是否为空?
为什么还要加volatile修饰变量?
如果不加锁的话,是线程不安全的,也就是有可能多个线程同时访问getInstance方法会得到两个实例化的对象。
如果给getInstance方法加锁,就每次访问mSingleton都需要加锁,增加了性能开销
第一次判空是为了判断是否已经实例化,如果已经实例化就直接返回变量,不需要加锁了。第二次判空是因为走到加锁这一步,如果线程A已经实例化,等B获得锁,进入的时候其实对象已经实例化完成了,如果不二次判空就会再次实例化。
加volatile是为了禁止指令重排。指令重排指的是在程序运行过程中,并不是完全按照代码顺序执行的,会考虑到性能等原因,将不影响结果的指令顺序有可能进行调换。所以初始化的顺序本来是这三步:
1)分配内存空间
2)初始化对象
3)将对象指向分配的空间
如果进行了指令重排,由于不影响结果,所以2和3有可能被调换。所以就变成了:
1)分配内存空间
2)将对象指向分配的空间
3)初始化对象
就有可能会导致,假如线程A中已经进行到第二步,线程B进入第二次判空的时候,判断mSingleton不为空,就直接返回了,但是实际此时mSingleton还没有初始化。