小姐姐的馈赠笔记

感想ymj小姐姐的无私奉献,感激涕零。东西很不错,当是用心良苦啊


1. 怎样判断一个对象是否线程安全?

(1) 该对象是否会被多个线程访问修改

假如对象会被多个线程访问,例如各种的ContextFactory

(2) 注意静态变量

由于静态变量是属于该类和该类下所有对象共享,可以直接通过类名访问和修改

3)  改变对象内部状态的方法调用.

当一个对象的属性会被多个线程修改时,需要进行同步操作.但并不代表不提供某属性的setter方法就可以万事安心.而真正需要关注的是,哪些内部方法的调用或对外公开的方法调用会导致对象内部属性(状态)的改变

(3) 单例

单例由于是全局唯一,所以单例对象会被所有线程所访问,而单例中的属性若允许进行修改,则会引发线程安全问题.当对象在Spring管理下默认是Singleton,当我们在三层架构开发下.DAOService中声明全局变量并对其进行操作,同样会引发线程安全问题。

2. 什么时候数据库语句提交?什么时候回滚?

执行语句中途发生错误则回滚到上次系统正确的状态,一般数据库用日志方式控制回滚。

3. Servlet是单例还是多例?

Servlet是单例的。

Servlet容器默认是采用单实例多线程的方式处理多个请求的:

1.当web服务器启动的时候(或客户端发送请求到服务器时),Servlet就被加载并实例化(只存在一个Servlet实例);

2.容器初始化化Servlet主要就是读取配置文件(例如tomcat,可以通过servlet.xml的<Connector>设置线程池中线程数目,初始化线程池通过web.xml,初始化每个参数值等等。

3.当请求到达时,Servlet容器通过调度线程(Dispatchaer Thread) 调度它管理下线程池中等待执行的线程(Worker Thread)给请求者;

4.线程执行Servlet的service方法;

5.请求结束,放回线程池,等待被调用;

JSP:当客户端第一次请求某一个JSP文件时,服务端把该JSP编译成一个CLASS文件,并创建一个该类的实例,然后创建一个线程处理CLIENT端的请求。如果有多个客户端同时请求该JSP文件,则服务端会创建多个线程。每个客户端请求对应一个线程。

均不是线程安全的

4. 数据库连接collection

5. 使用MongoDB,必须首先在MongoDB中创建 Database CollectionDatabase是相互独立的,每个Database都有自己的Collections,不同的database中,可以存在名字相同的collection,但是Database不是物理存储单位,MongoDBCollection为物理存储单位,每个collection都有自己的数据文件和index文件,这些文件以 .wt 结尾。 

6. 先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。

http(超文本传输协议)是一个基于请求与响应模式的、无状态的、应用层的协议,常基于TCP的连接方式。HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。

1. B/S模式(Browser/Server

Browser指的是Web浏览器,极少数事务逻辑在前端实现,但主要事务逻辑在服务器端实现,Browser客户端,WebApp服务器端和DB端构成所谓的三层架构。

B/S架构中,显示逻辑交给了Web浏览器,事务处理逻辑在放在了WebApp上,这样就避免了庞大的胖客户端,减少了客户端的压力。因为客户端包含的逻辑很少,因此也被成为瘦客户端。

优点:客户端无需安装,有Web浏览器即可。BS架构可以直接放在广域网上,通过一定的权限控制实现多客户访问的目的,交互性较强。BS架构无需升级多个客户端,升级服务器即可。

缺点:在跨浏览器上,BS架构不尽如人意。在速度和安全性上需要花费巨大的设计成本。客户端服务器端的交互是请求-响应模式,通常需要刷新页面,在Ajax风行后此问题得到了一定程度的缓解。

相对于C/SB/S具有如下优势:

1、分布性:可以随时进行查询、浏览等业务

2、业务扩展方便:增加网页即可增加服务器功能

3、维护简单方便:改变网页,即可实现所有用户同步更新

4、开发简单,共享性强,成本低,数据可以持久存储在云端而不必担心数据的丢失。

2. C/S模式(client/server

其客户端包含一个或多个在用户的电脑上运行的程序,而服务器端有两种,一种是数据库服务器端,客户端通过数据库连接访问服务器端的数据;另一种是Socket服务器端,服务器端的程序通过Socket与客户端的程序通信。

C/S 架构也可以看做是胖客户端架构。因为客户端需要实现绝大多数的业务逻辑和界面展示。这种架构中,作为客户端的部分需要承受很大的压力,因为显示逻辑和事务处理都包含在其中,通过与数据库的交互(通常是SQL或存储过程的实现)来达到持久化数据,以此满足实际项目的需要。

优点 C/S架构的界面和操作可以很丰富。安全性能可以很容易保证,实现多层认证也不难。由于只有一层交互,因此响应速度较快。

缺点:适用面窄,通常用于局域网中。用户群固定。由于程序需要安装才可使用,因此不适合面向一些不可知的用户。维护成本高,发生一次升级,则所有客户端的程序都需要改变。

1. 如何设计一个秒杀系统:前端(限制请求次数,限制同一IP的点击次数,限制一定数量的请求有效)后端(servlet单例多线程,请求放入阻塞队列,保证可靠。)

2. 线程的次序执行,join方法。

3. 分布式框架,服务器

分布式和集群(集群是个物理形态,分布式是个工作方式)

分布式:一个业务分拆多个子业务,部署在不同的服务器上

集群:同一个业务,部署在多个服务器上

例:小饭店原来只有一个厨师,切菜洗菜备料炒菜全干。后来客人多了,厨房一个厨师忙不过来,又请了个厨师,两个厨师都能炒一样的菜,这两个厨师的关系是集群。为了让厨师专心炒菜,把菜做到极致,又请了个配菜师负责切菜,备菜,备料,厨师和配菜师的关系是分布式,一个配菜师也忙不过来了,又请了个配菜师,两个配菜师关系是集群。

负载均衡集群:集群中所有的节点都处于活动状态,它们分摊系统的工作负载。这种集群可以在接到请求时,检查接受请求较少,不繁忙的服务器,并把请求转到这些服务器上。一般Web服务器集群、数据库集群和应用服务器集群都属于这种类型。

4. Cookiesession区别,session存储在服务器上,cookie存放在浏览器上(客户端),cookie怎样去连接session

第一次访问服务器,会生成一个session;(session在用户第一次访问服务器时创建,只有访问jspservlet时才会创建,只访问HTMLImage等静态资源并不会创建session

Response会返回一个sessionID,存放在会话cookie

cookie目的可以跟踪会话,也可以保存用户喜好或者保存用户名密码(将域名对应的cookie保存到硬盘中,下次访问的时候浏览器查找保存在硬盘中的与该域名对应的cookie填充),session用来跟踪会话。

      第一次访问一个网页。当客户端发送请求后,服务端会建立一个针对此请求发出客户的session对象,而且每个session都会有一个sessionID。服务端会自动将这个sessionID作为一个cookie附加到response上返回给客户端,这个cookie存放在浏览器内存中。我们每次对此网页发送的request都会附带着这个cookie,服务端收到这个请求后会都去cookie中取得这个sessionID,然后查询服务端是否存在一个对应此IDsession对象。如果有,可以直接使用此session;如果没有,则会新建一个。当浏览器关闭后,其所占的内存就会是放掉,cookie自然也就被清除了,此时我们不再保存有这个sessionID。所以再打开浏览器访问同一个页面时,由于没有sessionID,也就查不到对应的session对象,此时重新创建一个新的session对象。

5. Hashmaphashtable区别?

Entry对象唯一表示一个键值对,有四个属性:key,value,hash,entry(指向链表中下一个entry对象)

hashMap支持null键和null值,hashtable不可以。

hashMap(默认大小162*n扩容,然后重新计算HashMap中每个元素在数组中的位置)非线程安全,hashTable(默认11,2*n+1扩容)线程安全。

6. 用什么工具和方法分析线程问题。

VisualVM:监控应用程序的性能和内存占用情况、监控应用程序的线程、进行线程转储(Thread Dump)或堆转储(Heap Dump)、跟踪内存泄漏、监控垃圾回收器、执行内存和CPU分析,保存快照以便脱机分析应用程序。

包含远程监控Jboos服务;netstat -a | grep -i 2899 命令查看端口占有情况

7多线程操作字符串缓冲区下大量数据用Stringbufferstringbufferappend操作线程安全;单线程操作字符串缓冲区下大量数据,可使用StingBuilder获取更好的性能。

JvmString字符串的操作效率低,String是不可变类,每当用String操作字符串时,实际上是在不断的创建新的对象,把操作后的值放到新的对象里,把引用的指针指向新的对象,而原来的对象就会变为垃圾被GC回收掉。但是stringbufferstringbuilder则是在对同一个对象进行操作。

8.线程安全:线程安全就是多线程访问时,采用了加锁机制,只有一个线程访问结束另一个线程才可以进行访问。非线程安全则没有这样的保护机制。

线程安全一般都是全局变量和静态变量引起的。若每个线程对全局变量或静态变量只有读操作,一般来说是线程安全的,若多个线程执行写操作,则要考虑同步问题。

线程安全:线程安全就是多线程访问时,采用了加锁机制,只有一个线程访问结束另一个线程才可以进行访问。非线程安全则没有这样的保护机制。

线程安全一般都是全局变量和静态变量引起的。若每个线程对全局变量或静态变量只有读操作,一般来说是线程安全的,若多个线程执行写操作,则要考虑同步问题。

线程池:线程池在系统启动时创建大量空闲线程,程序将一个Runnable对象传给线程池,线程池就会启动一条线程来执行该线程对象的run方法,当run方法执行结束后,该线程并不会死亡,而是再次返回线程池中成为空闲线程,等待执行下一个Runnable对象的run方法。使用线程池可以有效地控制系统中并发线程的数量。

线程:进程中负责程序执行的单元,一个进程中至少有一个线程。

多线程:一个进程运行时产生了不止一个线程,在同一个应用程序中有多个功能流同时执行,多线程的切换是根据CPU切换完成。

1. 锁表

锁表的原理是数据库使用独占式封锁机制,当执行上面的语句时,对表进行锁住,直到发生commite 或者 回滚 或者退出数据库用户。

锁表的原因

A程序执行了对 tableA insert ,并还未 commite时,B程序也对tableA 进行insert 则此时会发生资源正忙的异常 就是锁表。

锁表常发生于并发而不是并行(并行时,一个线程操作数据库时,另一个线程是不能操作数据库的,cpu i/o 分配原则)

减少锁表的概率:

减少insert update delete 语句执行 到 commite 之间的时间。例如批量执行改为单个执行、优化sql自身的执行速度。如果异常对事物进行回滚。

2. 数据库索引原理:平衡二叉树和B+树。

不是索引字段越多越好,建立一棵二叉树需要空间,插入和变更数据需要调整二叉树结构。B树是多孩子节点的树。

3. 如何检查一个链表有没有环。

定义一个指针一次走两步,再定义一个指针一次走一步。如果两个指针相遇,则代表有环。

1. 集合索引(联合索引)

单一索引:在表的某一列上创建索引

联合索引:在多个列上联合创建索引

注意:查询条件中出现联合索引第一列,或者全部,则能使用联合索引。

2. 类加载机制

类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载,验证,准备,解析,初始化,使用和卸载七个阶段。

类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口

3. 3.GC回收机制

按代的垃圾回收机制:

新生代(Young generation): 绝大多数最新被创建的对象会被分配到这里,由于大部分对象在创建后会很快变得不可到达,所以很多对象被创建在新生代,然后消失。对象从这个区域消失的过程我们称之为minor GC“。

一个伊甸园空间 Eden + 两个幸存者空间Survivor

1.绝大多数刚刚被创建的对象会存放在伊甸园空间。

2.在伊甸园空间执行了第一次GC之后,存活的对象被移动到其中一个幸存者空间。

3.此后,在伊甸园空间执行GC之后,存活的对象会被堆积在同一个幸存者空间。

4.当一个幸存者空间饱和,还在存活的对象会被移动到另一个幸存者空间。之后会清空已经饱和的那个幸存者空间。

5.在以上的步骤中重复几次依然存活的对象,就会被移动到老年代

(其中一个幸存者空间一定是空的)

 

老年代(Old generation): 对象没有变得不可达,并且从新生代中存活下来,会被拷贝到这里。其所占用的空间要比新生代多。也正由于其相对较大的空间,发生在老年代上的GC要比新生代少得多。对象从老年代中消失的过程,我们称之为”major GC“(或者”full GC

持久代( permanent generation )也被称为方法区method area)。他用来保存类常量以及字符串常量。因此,这个区域不是用来永久的存储那些从老年代存活下来的对象。这个区域也可能发生GC。并且发生在这个区域上的GC事件也会被算为major GC。

4. 3.动态规划

动态规划的核心思想是巧妙的将问题拆分成多个子问题,通过计算子问题而得到整体问题的解。而子问题又可以拆分成更多的子问题,从而用类似递推迭代的方法解决要求的问题。

5. JAVA BIO,NIO,AIO的理解

同步和异步是针对应用程序和内核之间的交互完成的。

阻塞和非阻塞是针对于进程在访问数据的时候,根据IO操作的就绪状态来采取的不同方式。阻塞方式下读取或者写入函数将一直等待,而非阻塞方式下,读取或者写入函数会立即返回一个状态值。

同步阻塞:你到饭馆点餐,然后在那等着,还要一边喊:好了没啊!

同步非阻塞:在饭馆点完餐,就去遛狗了。不过溜一会儿就回饭馆喊一声:好了没啊!

异步阻塞:遛狗的时候,接到饭馆电话,说饭做好了,让您亲自去拿。

异步非阻塞:饭馆打电话说,我们知道您的位置,一会给送过去,安心遛狗就可以了。

一个IO操作分成两个步骤:发起IO请求实际的IO操作

阻塞和非阻塞的区别在于第一步,发起IO请求是否会阻塞。同步和异步的区别在于第二步,如果实际的IO读写阻塞请求进程,那么就是同步IO

同步阻塞IOJAVA BIO): 
    同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。

同步非阻塞IO(Java NIO) : 同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。用户进程也需要时不时的询问IO操作是否就绪,这就要求用户进程不停的去询问。 

异步阻塞IOJava NIO):  
   此种方式下是指应用发起一个IO操作以后,不等待内核IO操作的完成,等内核完成IO操作以后会通知应用程序,这其实就是同步和异步最关键的区别,同步必须等待或者主动的去询问IO是否完成,那么为什么说是阻塞的呢?因为此时是通过select系统调用来完成的,而select函数本身的实现方式是阻塞的,而采用select函数有个好处就是它可以同时监听多个文件句柄

Java AIO)异步非阻塞IO:  
   在此种模式下,用户进程只需要发起一个IO操作然后立即返回,等IO操作真正的完成以后,应用程序会得到IO操作完成的通知,此时用户进程只需要对数据进行处理就好了,不需要进行实际的IO读写操作,因为真正的IO读取或者写入操作已经由内核完成了。    

BIO方式适用于连接数目比较小且固定的架构。

NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器。

AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作。

综上所述,同步和异步是相对于应用和内核的交互方式而言的,同步 需要主动去询问,而异步的时候内核在IO事件发生的时候通知应用程序,而阻塞和非阻塞仅仅是系统在调用系统调用的时候函数的实现方式。

 

 

 


猜你喜欢

转载自blog.csdn.net/qq_21325705/article/details/79999040