目录
一.计算机网络
1.TCP的三次握手四次挥手
三次握手
四次挥手(详细说明)
TCP和UDP的区别
为什么TCP连接的时候是3次?2次不可以吗?
为什么TCP连接的时候是3次,关闭的时候却是4次?
2.HTTP 与 HTTPS
什么是HTTP
HTTP 与 HTTPS的区别
一个完整的http请求过程:
3.GET和POST
4.TCP/IP协议
5.四层协议,五层协议和七层协议的关系
二.操作系统
1.死锁
什么是死锁?
死锁产生有哪些条件?
对于死锁,主要有4种解决策略
2.进程和线程
什么是进程?
什么是线程?
进程与线程有什么区别?
进程调度的几种方式
3.分时系统和实时系统
分时系统
实时系统
分时系统和实时系统的区别
4.多线程
概念
为什么要使用多线程?
缺点:
为什么不能直接调用 run() 方法:
什么是上下文切换:
多线程模型
多线程和多进程的区别
三.JAVA基础
1.Java注解
2.线程池
3.类对象
4.面向对象和面向过程的区别
5.线程安全和线程非安全
6.线程安全手段
1) 互斥同步
2) 非阻塞同步
3) 无同步方案
7.Jni
8.JMM和JVM
JMM:
JVM:
9.set和map的区别
概述:
集合 与 字典 的区别:
Set:
Map:
10.设计模式
概念:
都知道哪些设计模式
11.Java 中,为什么不允许从静态方法中访问非静态变量?
12.java泛型
概念:
作用:
13.volatile关键字
概念:
特性:
14.equals()方法和hashCode方法
1)equals()方法
2)hashcode()方法
3)总结
15.synchronized关键字
16.手写单例模式
1)懒汉式
线程安全的懒汉式
饿汉式
17.常用的算法
18.容器
(1)List:列表,是一个接口。它的实现类常用的有LinkedList、ArrayList和Vector。
(2)Set:集合,和数学中的集合类似。
(3)Map:是一类重要的数据结构。类似于数学中的函数,key对应自变量x、value对应因变量y、散列函数对用f。
(4)工具类
四.Android基础
1.Android四大组件
1)活动(activity)
2)服务(Service)
3)广播接受者(Broadcast Receive)
4)内容提供者(Content Provider)
TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议,在发送数据前,通信双方必须在彼此间建立一条连接。所谓的“连接”,其实是客户端和服务端保存的一份关于对方的信息,如ip地址、端口号等。
TCP可以看成是一种字节流,它会处理IP层或以下的层的丢包、重复以及错误问题。在连接的建立过程中,双方需要交换一些连接的参数。这些参数可以放在TCP头部。
一个TCP连接由一个4元组构成,分别是两个IP地址和两个端口号。一个TCP连接通常分为三个阶段:连接、数据传输、退出(关闭)。
通过三次握手建立一个链接,通过四次挥手来关闭一个连接。当一个连接被建立或被终止时,交换的报文段只包含TCP头部,而没有数据。
三次握手的本质是确认通信双方收发数据的能力
首先,我让信使运输一份信件给对方,对方收到了,那么他就知道了我的发件能力和他的收件能力是可以的。
于是他给我回信,我若收到了,我便知我的发件能力和他的收件能力是可以的,并且他的发件能力和我的收件能力是可以。
然而此时他还不知道他的发件能力和我的收件能力到底可不可以,于是我最后回馈一次,他若收到了,他便清楚了他的发件能力和我的收件能力是可以的。
四次挥手的目的是关闭一个连接
第一次挥手:客户端发送一个FIN=M,用来关闭客户端到服务器端的数据传送,客户端进入FIN_WAIT_1状态。意思是说"我客户端没有数据要发给你了",但是如果你服务器端还有数据没有发送完成,则不必急着关闭连接,可以继续发送数据。
第二次挥手:服务器端收到FIN后,先发送ack=M+1,告诉客户端,你的请求我收到了,但是我还没准备好,请继续你等我的消息。这个时候客户端就进入FIN_WAIT_2 状态,继续等待服务器端的FIN报文。
第三次挥手:当服务器端确定数据已发送完成,则向客户端发送FIN=N报文,告诉客户端,好了,我这边数据发完了,准备好关闭连接了。服务器端进入LAST_ACK状态。
第四次挥手:客户端收到FIN=N报文后,就知道可以关闭连接了,但是他还是不相信网络,怕服务器端不知道要关闭,所以发送ack=N+1后进入TIME_WAIT状态,如果Server端没有收到ACK则可以重传。服务器端收到ACK后,就知道可以断开连接了。客户端等待了2MSL后依然没有收到回复,则证明服务器端已正常关闭,那好,我客户端也可以关闭连接了。最终完成了四次握手。
TCP | UDP | |
是否连接 | 面向连接 | 面向非连接 |
传输可靠性 | 可靠 | 不可靠 |
应用场合 | 传输少量数据 | 传输大量数据 |
速度 | 慢 | 快 |
假设有A和B两端要进行通信,
1, 第一次:首先A发送一个(SYN)到B,意思是A要和B建立连接进行通信;如果是只有一次握手的话,这样肯定是不行的,A压根都不知道B是不是收到了这个请求。
2, 第二次:B收到A要建立连接的请求之后,发送一个确认(SYN+ACK)给A,意思是收到A的消息了,B这里也是通的,表示可以建立连接;
如果只有两次通信的话,这时候B不确定A是否收到了确认消息,有可能这个确认消息由于某些原因丢了。
3, 第三次:A如果收到了B的确认消息之后,再发出一个确认(ACK)消息,意思是告诉B,这边是通的,然后A和B就可以建立连接相互通信了;
这个时候经过了三次握手,A和B双方确认了两边都是通的,可以相互通信了,已经可以建立一个可靠的连接,并且可以相互发送数据。
4, 第四次:这个时候已经不需要B再发送一个确认消息了,两边已经通过前三次建立了一个可靠的连接,如果再发送第四次确认消息的话,就浪费资源了。
如果第二个报文段B发出的(SYN+ACK)分别发送的话,也是可以理解为四次,但是被优化了,一起发送了。
因为只有在客户端和服务端都没有数据要发送的时候才能断开TCP。而客户端发出FIN报文时只能保证客户端没有数据发了,服务端还有没有数据发客户端是不知道的。而服务端收到客户端的FIN报文后只能先回复客户端一个确认报文来告诉客户端我服务端已经收到你的FIN报文了,但我服务端还有一些数据没发完,等这些数据发完了服务端才能给客户端发FIN报文(所以不能一次性将确认报文和FIN报文发给客户端,就是这里多出来了一次)。
HTTP 是一个在计算机世界里专门在两点之间传输文字、图片、音频、视频等超文本数据的约定和规范
1、https协议需要到CA申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl/tls加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL/TLS+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
浏览器发起请求-> 解析域名得到ip进行TCP连接 ->浏览器发送HTTP请求和头信息发送->服务器对浏览器进行应答,响应头信息和浏览器所需的内容-> 关闭TCP连接或保持-> 浏览器得到数据数据进行操作。
浏览器和服务器的交互是通过HTTP协议执行的,而GET和POST是HTTP协议中的两种方法。
HTTP全称为Hyper Text Transfer Protocol,中文翻译为超文本传输协议,目的是保证浏览器与服务器之间的通信。HTTP的工作方式是客户端与服务器之间的请求-应答协议。
HTTP协议中定义了浏览器和服务器进行交互的不同方法,基本方法有4种,分别是GET,POST,PUT,DELETE。这四种方法可以理解为,对服务器资源的查,改,增,删。
GET和POST区别
对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。
TCP/IP(Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议)是指能够在多个不同网络间实现信息传输的协议簇。TCP/IP协议不仅仅指的是TCP 和IP两个协议,而是指一个由FTP、SMTP、TCP、UDP、IP等协议构成的协议簇, 只是因为在TCP/IP协议中TCP协议和IP协议最具代表性,所以被称为TCP/IP协议。
注:五层协议的体系结构只是为了介绍网络原理而设计的,实际应用还是 TCP/IP 四层体系结构。
卧槽!牛皮了,头一次见有大佬把TCP/IP三次握手四次挥手解释的这么明白 - 知乎原文:https://blog.csdn.net/ThinkWo...计算机网络体系结构在计算机网络的基本概念中,分层次的体系结构是最基本的。计算机网络体系结构的抽象概念较多,在学习时要多思考。这些概念对后面的学习很有帮助。 网络…https://zhuanlan.zhihu.com/p/141396896
在两个或多个并发进程中,如果一个进程集合中的每个进程都在等待只能由该进程集合中的其他进程才能引发的事件,那么该进程集合就产生了死锁。
死锁产生的根本原因是多个进程竞争资源时,进程的推进顺序出现不正确。互斥:每个资源要么已经分配给了一个进程,要么就是可用的。
占有和等待:已经得到了某个资源的进程可以再请求新的资源。
不可抢占:已经分配给一个进程的资源不能强制性地被抢占,它只能被占有它的进程显式地释放。
环路等待:有两个或者两个以上的进程组成一条环路,该环路中的每个进程都在等待下一个进程所占有的资源。
鸵鸟策略、死锁预防、死锁避免、死锁检测和恢复
指在系统中正在运行的一个应用程序;程序一旦运行就是进程;进程——资源分配的最小单位。
系统分配处理器时间资源的基本单元,或者说进程之内独立执行的一个单元执行流。线程——程序执行的最小单位。
1.进程要分配一大部分的内存,而线程只需要分配一部分栈就可以了.
2.一个程序至少有一个进程,一个进程至少有一个线程.
3.进程是资源分配的最小单位,线程是程序执行的最小单位。
4.一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行.
一、先来先服务和短作业(进程)优先调度算法
二、高优先权优先调度算法
1.优先权调度算法的类型
1) 非抢占式优先权算法
2) 抢占式优先权调度算法
2.高响应比优先调度算法
分时系统是指在一个系统中多个用户分时地使用同一台计算机;
实时系统是指计算机及时响应外部事件地请求并在规定时限内完成对该事件地处理,控制所有实时外设和实时任务协调一致地运行。
(1)分时系统的目标是提供一种通用性很强的系统,有较强的交互能力;而实时系统则大都是具有特殊用途的专用系统,交互能力略差。
(2)分时系统对响应时间虽有要求,但一般来说,响应时间由人所能承受的等待时间来确定;而实时系统对响应时间要求很高,一般由控制系统或信息处理磁头所能接受的延迟时间来决定。
多线程是为了同步完成多项任务,不是为了提高运行效率,而是为了提高资源使用效率来提高系统的效率。线程是在同一时间需要完成多项任务的时候实现的。
·最简单的比喻多线程就像火车的每一节车厢,而进程则是火车。车厢离开火车是无法跑动的,同理火车也不可能只有一节车厢。多线程的出现就是为了提高效率。同时它的出现也带来了一些问题。
先总体上:
再深入到计算机底层:
并发编程的目的就是为了能提高程序的执行效率提高程序运行速度,但是并发编程并不总是能提高程序运行速度的,而并发编程可能会遇到很多问题,比如:内存泄漏、上下文切换、死锁等,还有受限于硬件和软件和资源闲置问题。
我们调用 start() 方法时会执行 run() 方法,new 一个 Thread,线程进入了新建状态;调用 start() 方法,会启动一个线程并使线程进入就绪状态,当分配到时间片后就可以开始运行了。start() 会执行线程的相应准备工作,然后自动执行 run() 方法的内容,这是真正的多线程工作。而直接执行 run() 方法,会把 run() 方法当成一个 main 线程下的普通方法去执行,并不会在某个线程中执行它,所以这不是多线程工作。
总之:调用 start() 方法可启动线程并使线程进入就绪状态,而 run() 方法只是 thread 的一个普通方法,还是在主线程里执行的。
多线程编程中一般线程的个数都大于 CPU 核的个数,而一个 CPU 核在任意时刻只能被一个线程使用,为了让这些县城都能得到有效执行,CPU 采取的策略是为每个线程分配时间片并轮转的形式。当一个线程是时间片用完的时候就会重新处于就绪状态让给其他线程使用,这个过程就属于一次上下文切换。也就是:当任务执行完, CPU 时间片切换到另一个任务之前会先保存自己的状态,以便于再切换回这个任务时,可以加载这个任务的状态。任务从保持到再加载的过程就是一个上下文切换。
上下文切换通常是计算密集型的。也就是说,它需要相当可观的处理器时间,在每秒几十上百次的切换中,每次切换都需要纳秒量级的时间。所以,上下文切换对系统来说意味着消耗大量的 CPU 时间,事实上,可能是操作系统中时间消耗最大的操作。
Linux 相比与其他操作系统(包括其他类 Unix 系统)有很多的优点,其中有一项就是,其上下文切换和模式切换的时间消耗非常少。
多线程模型有三种
多对多关系线程模型是任意数量N的用户线程到相等或者小于N的内核线程的多路复用。
下图显示了多对多线程模型,其中6个用户级线程与6个内核级线程进行多路复用。在此模型中,开发人员可以根据需要创建任意数量的用户线程,并且相应的内核线程可以在多处理器计算机上并行运行。此模型提供了并发的最佳准确性,当线程执行阻塞系统调用时,内核可以调度另一个线程来执行。
多对一模型将许多用户级线程映射到一个内核级线程。线程管理由在用户空间由线程库中完成。当线程进行阻塞系统调用时,整个进程将被阻止。 一次只有一个线程可以访问内核,因此多个线程无法在多处理器上并行运行。
如果用户级线程库在操作系统中以系统不支持它们的方式实现的,则内核线程使用多对一关系模式。
用户级线程与内核级线程之间存在一对一的关系。与多对一模型相比,此模型提供更多并发性。 当线程进行阻塞系统调用时,它还允许另一个线程运行。 它支持多个线程在微处理器上并行执行。
该模型的缺点是创建用户线程时需要相应的内核线程。 OS / 2,Windows NT和Windows 2000使用一对一的关系模型。
多进程中占用内存多,切换复杂,CPU利用率低;多线程中占用内存少,切换简单,CPU利用率高。多进程中编程简单,调试简单;多线程中编程复杂,调试复杂。多进程中进程间不会相互影响;多线程中一个线程挂掉将导致整个进程挂掉。
Java 并发基础知识 - 意无尽 - 博客园一、什么是线程和进程? 进程: 是程序的一次执行过程,是系统运行程序的基本单元(就比如打开某个应用,就是开启了一个进程),因此进程是动态的。系统运行一个程序即是一个程序从创建、运行到消亡的过程。 在https://www.cnblogs.com/reformdai/p/11039843.html
Java 定义了一套注解,共有 7 个,3 个在 java.lang 中,剩下 4 个在 java.lang.annotation 中。
作用在其他注解的注解(或者说 元注解)是:
从 Java 7 开始,额外添加了 3 个注解:
Java通过Executors提供四种线程池,分别为
类与对象时整个面向对象中最基础的组成单元。
类:是抽象的概念集合,表示的是一个共性的产物,类之中定义的是属性和行为(方法);
对象:对象是一种个性的表示,表示一个独立的个体,每个对象拥有自己独立的属性,依靠属性来区分不同对象。
类是对象的模板,对象是类的实例。类只有通过对象才可以使用,而在开发之中应该先产生类,之后再产生对象。类不能直接使用,对象是可以直接使用的。
面向对象是一种现在最为流行的程序设计方法,几乎现在的所有应用都以面向对象为主了,最早的面向对象的概念实际上是由IBM提出的,在70年代的Smaltalk语言之中进行了应用,后来根据面向对象的设计思路,才形成C++,而由C++产生了Java这门面向对象的编程语言。
但是在面向对象设计之前,广泛采用的是面向过程,面向过程只是针对于自己来解决问题。面向过程的操作是以程序的基本功能实现为主,实现之后就完成了,也不考虑修改的可能性,面向对象,更多的是要进行子模块化的设计,每一个模块都需要单独存在,并且可以被重复利用,所以,面向对象的开发更像是一个具备标准的开发模式。
在面向对象定义之中,也规定了一些基本的特征:
(1)封装:保护内部的操作不被破坏;
(2)继承:在原本的基础之上继续进行扩充;
(3)多态:在一个指定的范围之内进行概念的转换。
线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。
线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据
互斥同步(Mutual Exclusion & Synchroniztion)是最常见的一种并发正确性保障手段。
Java Native Interface(JNI,Java本地接口)是Java语言的本地编程接口。在java程序中,我们可以通过JNI实现一些用java语言不便实现的功能,如下:
1)标准的java类库没有提供你的应用程序所需要的功能,通常这些功能是平台相关的(只能由其他语言编写)。
2)你希望使用一些已经有的类库或者应用程序,而他们并非用java语言编写的。
3)程序的某些部分对速度要求比较苛刻,你选择用汇编或者c语言来实现并在java语言中调用他们。
4)为了应用的安全性,会将一些复杂的逻辑和算法通过本地代码(C或C++)来实现,本地代码比字节码难以破解。
JMM:JAVA内存模型(java memory model) 是一种抽象概念,并不真实存在,它描述的是一组规则或规范,通过这组规范定义了程序中各个变量(实例字段,静态字段和构成数组对象的元素)的访问方式。
Java 内存模型的主要目标是定义程序中各个变量的访问规则,也就是在虚拟机中将变量存储到内存,以及从内存中取出变量这样的底层细节。
JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的
引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。
Java 虚拟机在执行 Java 程序过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则是以来用户线程的启动和结束而建立和销毁。Java 虚拟机所管理的内存将会包括以下几个运行区域,如图所示。
第一,JVM分为五个区域:虚拟机栈、本地方法栈、方法区、堆、程序计数器。
第二,JVM五个区中虚拟机栈、本地方法栈、程序计数器为线程私有,方法区和堆为线程共享区。
第三,JVM不同区域的占用内存大小不同,一般情况下堆最大,程序计数器较小。那么最大的区域放Java中最多的“对象”了。
设计模式是世界上各种各样程序员用来解决特定设计问题的尝试和测试的方法。设计模式是代码可用性的延伸
单例模式,依赖注入,工厂模式,装饰模式,观察者模式。
Java 中不能从静态上下文访问非静态数据只是因为非静态变量是跟具体的对象实例关联的,而静态的却没有和任何实例关联。
Java泛型是J2 SE1.5中引入的一个新特性,其本质是参数化类型,也就是说所操作的数据类型被指定为一个参数(type parameter)这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法
第一是泛化。可以用T代表任意类型Java语言中引入泛型是一个较大的功能增强不仅语言、类型系统和编译器有了较大的变化,以支持泛型,而且类库也进行了大翻修,所以许多重要的类,比如集合框架,都已经成为泛型化的了,这带来了很多好处。
第二是类型安全。泛型的一个主要目标就是提高Java程序的类型安全,使用泛型可以使编译器知道变量的类型限制,进而可以在更高程度上验证类型假设。如果不用泛型,则必须使用强制类型转换,而强制类型转换不安全,在运行期可能发生ClassCast Exception异常,如果使用泛型,则会在编译期就能发现该错误。
第三是消除强制类型转换。泛型可以消除源代码中的许多强制类型转换,这样可以使代码更加可读,并减少出错的机会。
第四是向后兼容。支持泛型的Java编译器(例如JDK1.5中的Javac)可以用来编译经过泛型扩充的Java程序(Generics Java程序),但是现有的没有使用泛型扩充的Java程序仍然可以用这些编译器来编译。
volatile 是java虚拟机提供的轻量级同步机制
可见性
不保证原子性
禁止指令重排
public boolean equals(Object obj) {
return (this == obj);
}
equals()方法是根类Obeject中的方法
默认的equals方法,直接调用==,比较对象地址。不同的子类,可以重写此方法,进行两个对象的equals的判断。
hashCode是根类Obeject中的方法。Object中的hashCode() 默认返回对象的32位jvm内存地址。也就是说如果对象不重写该方法,则返回相应对象的32为JVM内存地址。
I.绑定当equals方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。
II.绑定原因。Hashtable实现一个哈希表,为了成功地在哈希表中存储和检索对象,用作键的对象必须实现 hashCode
方法和 equals
方法。同(1),必须保证equals相等的对象,hashCode
也相等。因为哈希表通过hashCode检索对象。
III.默认。
hashCode 默认返回对象在JVM中的存储地址。
equal比较对象,默认也是比较对象在JVM中的地址,同==
java中的==、equals()、hashCode()源码分析 - 旭东的博客 - 博客园在java编程或者面试中经常会遇到 == 、equals()的比较。自己看了看源码,结合实际的编程总结一下。1. == java中的==是比较两个对象在JVM中的地址。比较好理解。看下面的代码:1 phttps://www.cnblogs.com/xudong-bupt/p/3960177.html
synchronized是Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码。
当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。然而,当一个线程访问object的一个加锁代码块时,另一个线程仍可以访问该object中的非加锁代码块。
synchronized是Java中的关键字,是一种同步锁。
它修饰的对象有以下几种:
1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。
使用单例模式的意图就是保证一个类仅有一个实例,并提供一个访问它的全局访问点。
所谓懒汉,就是需要的时候才初始化对象,也就是懒加载。如下代码所示,我们在获取Instance对象时判断对象是否已经创建,如果未创建,才进行创建对象,如果对象已经创建,则直接返回。
懒汉式的问题在于,如果多个线程调用getInstance方法,创建方法是可能被执行多次的,换言之就是线程不安全的。
/**
* 懒汉式
*
* @author freedom wang
* @date 2021-01-12 07:48:33
*/
public class Singleton1 {
private static Singleton1 instance;
private Singleton1() {
}
public static Singleton1 getInstance() {
if (instance == null) {
instance = new Singleton1();
}
return instance;
}
}
懒汉式是线程不安全的,加上锁就能让它变得线程安全。我们对getInstance
方法加上synchronized
关键字,让多线程对于getInstance
方法的调用变成线性调用。这样子就保证了线程安全了。
public class Singleton1 {
private static Singleton1 instance;
private Singleton1() {
}
public static synchronized Singleton1 getInstance() {
if (instance == null) {
instance = new Singleton1();
}
return instance;
}
}
在类加载的时候,就创建单例对象。静态变量的赋值操作是类加载过程的最后一步初始化过程中执行的,也就是在
方法中。饿汉模式避免了多线程的并发问题,但是也导致了内存的浪费。
public class Singleton2 {
private static Singleton2 instance = new Singleton2();
private Singleton2() {
}
public static Singleton2 getInstance() {
if (instance == null) {
instance = new Singleton2();
}
return instance;
}
}
面试题:手写单例模式_匿迹-CSDN博客_手写单例面试题:手写单例模式面试题:手写单例模式二级目录三级目录面试题:手写单例模式二级目录三级目录https://blog.csdn.net/wang465745776/article/details/112417480
In-place:不占用额外内存
Out-place:占用额外内存
容器可以管理对象的生命周期、对象与对象之间的依赖关系,您可以使用一个配置文件(通常是XML),在上面定义好对象的名称、如何产生(Prototype 方式或Singleton 方式)、哪个对象产生之后必须设定成为某个对象的属性等,在启动容器之后,所有的对象都可以直接取用,不用编写任何一行程序代码来产生对象,或是建立对象与对象之间的依赖关系。
Java容器类包含List、ArrayList、Vector及map、HashTable、HashMap、Hashset
LinkedList
ArrayList
不适合频繁删除和插入
操作。对于需要经常进行查询的数据建议采用此结构。Vector
Vector用法和ArrayList用法很相似,它们的区别在于Vector是线程同步的而且Vector有另外的遍历方式
HashSet、LinkedHashSet、TreeSet里面存放的都要是对象,不能是基本数据类型。
HashSet
基于散列函数的集和,采用HashMap实现,可以容纳null元素,不支持同步(可以通过Collections.synchronizedSet(new HashSet<…>()来使它同步)
HashLinkedSet
继承HashSet ,基于散列函数和双向链表的集和,可以容纳null元素,通过双向链表维护了插入顺序,从而支持排序,但不支持同步(可以通过Collections.synchronizedSet(new HashSet<…>()来使它同步)
TreeSet
基于树结构的集和,印次支持排序,不能容纳null元素,同样不支持同步
总结
Hashtable
key和value都不能为空,HashTable是线程安全的、同步的,但只适合用于小数据量
HashMap
HashMap允许有null,不支持同步(支持通过Collections.synchronizedMap(new Map<…,…>() 实现同步),所以线程不安全。但可以存储大量数据
LinkedHashMap
基于双向链表用于维持插入顺序的HashMap,继承自HashMap
TreeMap
基于红黑树的Map,可以根据key的自然排序或者compareTo方法排序输出
Properties
继承自Hashtable。特有的方法有load()、store()等等。
总结
Map的种类有很多,根据实际情况选择合适的Map。
Arrays
Arrays处理的对象是数组,常用的方法包括排序sort、查找binarySearch、拷贝copy等等
Collections
Collections可以操作collections接口及其所有子类、常用的用法和Arrays差不多。但它的sort方法要求被排序对象实现了compareable接口或者传入一个compactor对象(主要针对某些类不能去被修改)
总结
Arrays和Collections着两个工具类能够帮我们做很多事情,所以要熟练的应用。避免重复造轮子。
java容器超详细_pony的博客-CSDN博客_java容器前言java容器是前人为我们提供的一套用于存储数据和对象的工具。如果你学过C++的STL,可以与之类比。java容器又可以称为Java Collection Framework(JCF)。里面除了存储对象的容器之外,还提供了一套用于处理和操作容器里面的对象的一套工具类。整体框架:下面将介绍List、Set、Map以及工具类Collections和Arrays。ListList:列表,...https://blog.csdn.net/qq_43969123/article/details/105804956
Android 开发的四大组件分别是:活动(activity),用于表现功能;服务(service),后台运行服务,不提供界面呈现;广播接受者(Broadcast Receive),勇于接收广播;内容提供者(Content Provider),支持多个应用中存储和读取数据,相当于数据库。
Activity的生命周期
在Android中会维持一个Activity Stack(Activity栈),当一个新的Activity创建时,它就会放到栈顶,这个Activity就处于运行状态。当再有一个新的Activity被创建后,会重新压人栈顶,而之前的Activity则会在这个新的Activity底下,就像枪梭压入子弹一样。而且之前的Activity就会进入后台。
一个Activity实质上有四种状态:
a.运行中(Running/Active):这时Activity位于栈顶,是可见的,并且可以用户交互。
b.暂停(Paused):当Activity失去焦点,不能跟用户交互了,但依然可见,就处于暂停状态。当一个新的非全屏的Activity或者一个透明的Activity放置在栈顶,Activity就处于暂停状态;这个时候Activity的各种数据还被保持着;只有在系统内存在极低的状态下,系统才会自动的去销毁Activity。
c.停止(Stoped):当一个Activity被另一个Activity完全覆盖,或者点击HOME键退入了后台,这时候Activity处于停止状态。这里有些是跟暂停状态相似的:这个时候Activity的各种数据还被保持着;当系统的别的地方需要用到内容时,系统会自动的去销毁Activity。
d.销毁(Detroyed):当我们点击返回键或者系统在内存不够用的情况下就会把Activity从栈里移除销毁,被系统回收,这时候,Activity处于销毁状态。
service(服务)是安卓中的四大组件之一,它通常用作在后台处理耗时的逻辑,与Activity一样,它存在自己的生命周期,也需要在AndroidManifest.xml配置相关信息。
服务并不是运行在一个独立的进程当中的,而是依赖于创建服务时所在的应用程序进程。与某个应用程序进程被杀掉时,所有依赖于该进程的服务也会停止运行。另外.也不要被服务的后台概念所迷惑,实际上服务并不会自动开启线程,所有的代码都是默认运行在主线程当中的。也就是说,我们需要在服务的内部手动创建子线程,并在这里执行具体的任务,否则就有可能出现主线程被阻塞住的情况。
在Android中,广播是一种广泛运用的在应用程序之间传输信息的机制。而广播接收器是对发送出来的广播进行过滤接受并响应的一类组件。可以使用广播接收器来让应用对一个外部时间做出响应。例如,当电话呼入这个外部事件到来时,可以利用广播接收器进行处理。当下载一个程序成功完成时,仍然可以利用广播接收器进行处理。广播接收器不NotificationManager来通知用户这些事情发生了。广播接收器既可以在AndroidManifest.xml中注册,也可以在运行时的代码中使用Context.registerReceive()进行注册。只要是注册了,当事件来临时,即使程序没有启动,系统也在需要的时候启动程序。各种应用还可以通过使用Context.sendBroadcast()将它们自己的Intent广播给其他应用程序。
(1)android平台提供了Content Provider使一个应用程序的指定数据集提供给其他应用程序。其他应用可以通过ContentResolver类从该内容提供者中获取或存入数据。
(2)只有需要在多个应用程序间共享数据是才需要内容提供者。例如,通讯录数据被多个应用程序使用,且必须存储在一个内容提供者中。它的好处是统一数据访问方式。
(3)ContentProvider实现数据共享。ContentProvider用于保存和获取数据,并使其对所有应用程序可见。这是不同应用程序间共享数据的唯一方式,因为android没有提供所有应用共同访问的公共存储区。
(4)开发人员不会直接使用ContentProvider类的对象,大多数是通过ContentResolver对象实现对ContentProvider的操作。
(5)ContentProvider使用URI来唯一标识其数据集,这里的URI以content://作为前缀,表示该数据由ContentProvider来管理。