Java软件开发面试题~1(含答案)

1、HTTP与TCP的区别联系

  1、http是在应用层的无状态通信协议。tcp是在传输层的面向连接的可靠的流协议。

  2、http连接的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。是建立在TCP协议之上的协议。

   1)在HTTP 1.0中,客户端的每次请求都要求建立一次单独的连接,在处理完本次请求后,就自动释放连接。

     2)在HTTP 1.1中则可以在一次连接中处理多个请求,并且多个请求可以重叠进行,不需要等待一个请求结束后再发送下一个请求。

  TCP协议可以对上层网络提供接口,使上层网络数据的传输建立在“无差别”的网络之上。TCP连接的特点是需要进行三次握手。

  第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;

  第二次握手:服务器收到syn包,必须发送确认客户SYN的ACK包(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;

  第三次握手:客户端收到服务器的SYN+ACK包。向服务器发送确认包(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。

2、JUC包了解多少,线程池了解多少

为什么要有线程池?

由于线程的生命周期中包括,创建-就绪-运行-阻塞-死亡 阶段,当我们处理的任务数目比较小的时候,我们可以自己创建几个线程来处理相应的任务,但是有大量的任务时,由于创建和销毁线程都需要很大的开销,运用线程池就可以大大的缓解这些内存开销很大的问题。

ThreadPoolExecutor是线程池类。对于线程池,可以通俗的将它理解为"存放一定数量线程的一个线程集合。线程池允许若个线程同时允许,允许同时运行的线程数量就是线程池的容量;当添加的到线程池中的线程超过它的容量时,会有一部分线程阻塞等待。线程池会通过相应的调度策略和拒绝策略,对添加到线程池中的线程进行管理。"

 

newSignalExecutor()返回一个包含单线程的Executor,将多个任务交给Executor时,这个线程处理完一个任务后会接着处理下一个任务,若该线程出现异常,将会有一个新的线程来替代它

 

newFixedThreadPool()返回一个包含指定数目线程数的线程池,如果任务数量多于线程数目的话,那么没有执行的任务必须等待,直到任务完成为止

 

newCachedThreadPool()根据用户的任务数目创建相应的线程来处理,该线程池不会对线程的数目加以限制,完全依赖于虚拟机能创建的线程输入,但是可能会引起内存不足。

 

3、介绍一下ListBlockingQueue与ArrayBlockingQueue

 

ArrayBlockingQueue 

ArrayBlockingQueue是数组实现的线程安全的有界的阻塞队列。
线程安全是指,ArrayBlockingQueue内部通过“互斥锁”保护竞争资源,实现了多线程对竞争资源的互斥访问。而有界,则是指ArrayBlockingQueue对应的数组是有界限的。 阻塞队列,是指多线程访问竞争资源时,当竞争资源已被某线程获取时,其它要获取该资源的线程需要阻塞等待;而且,ArrayBlockingQueue是按 FIFO(先进先出)原则对元素进行排序,元素都是从尾部插入到队列,从头部开始返回。注意:ArrayBlockingQueue不同于ConcurrentLinkedQueue,ArrayBlockingQueue是数组实现的,并且是有界限的;而ConcurrentLinkedQueue是链表实现的,是无界限的。

说明
    1. ArrayBlockingQueue继承于AbstractQueue,并且它实现了BlockingQueue接口。
    2. ArrayBlockingQueue内部是通过Object[]数组保存数据的,也就是说ArrayBlockingQueue本质上是通过数组实现的。ArrayBlockingQueue的大小,即数组的容量是创建ArrayBlockingQueue时指定的。
    3. ArrayBlockingQueue与ReentrantLock是组合关系,ArrayBlockingQueue中包含一个ReentrantLock对象(lock)。ReentrantLock是可重入的互斥锁,ArrayBlockingQueue就是根据该互斥锁实现“多线程对竞争资源的互斥访问”。而且,ReentrantLock分为公平锁和非公平锁,关于具体使用公平锁还是非公平锁,在创建ArrayBlockingQueue时可以指定;而且,ArrayBlockingQueue默认会使用非公平锁。
    4. ArrayBlockingQueue与Condition是组合关系,ArrayBlockingQueue中包含两个Condition对象(notEmpty和notFull)。而且,Condition又依赖于ArrayBlockingQueue而存在,通过Condition可以实现对ArrayBlockingQueue的更精确的访问 -- (01)若某线程(线程A)要取数据时,数组正好为空,则该线程会执行notEmpty.await()进行等待;当其它某个线程(线程B)向数组中插入了数据之后,会调用notEmpty.signal()唤醒“notEmpty上的等待线程”。此时,线程A会被唤醒从而得以继续运行。(02)若某线程(线程H)要插入数据时,数组已满,则该线程会它执行notFull.await()进行等待;当其它某个线程(线程I)取出数据之后,会调用notFull.signal()唤醒“notFull上的等待线程”。此时,线程H就会被唤醒从而得以继续运行。

ListBlockingQueue

 

  LinkedBlockingQueue是一个单向链表实现的阻塞队列。该队列按 FIFO(先进先出)排序元素,新元素插入到队列的尾部,并且队列获取操作会获得位于队列头部的元素。链接队列的吞吐量通常要高于基于数组的队列,但是在大多数并发应用程序中,其可预知的性能要低。

 

此外,LinkedBlockingQueue还是可选容量的(防止过度膨胀),即可以指定队列的容量。如果不指定,默认容量大小等于Integer.MAX_VALUE。

说明
1. LinkedBlockingQueue继承于AbstractQueue,它本质上是一个FIFO(先进先出)的队列。
2. LinkedBlockingQueue实现了BlockingQueue接口,它支持多线程并发。当多线程竞争同一个资源时,某线程获取到该资源之后,其它线程需要阻塞等待。
3. LinkedBlockingQueue是通过单链表实现的。
(01) head是链表的表头。取出数据时,都是从表头head处插入。
(02) last是链表的表尾。新增数据时,都是从表尾last处插入。
(03) count是链表的实际大小,即当前链表中包含的节点个数。
(04) capacity是列表的容量,它是在创建链表时指定的。
(05) putLock是插入锁,takeLock是取出锁;notEmpty是“非空条件”,notFull是“未满条件”。通过它们对链表进行并发控制。
       LinkedBlockingQueue在实现“多线程对竞争资源的互斥访问”时,对于“插入”和“取出(删除)”操作分别使用了不同的锁。对于插入操作,通过“插入锁putLock”进行同步;对于取出操作,通过“取出锁takeLock”进行同步。
       此外,插入锁putLock和“非满条件notFull”相关联,取出锁takeLock和“非空条件notEmpty”相关联。通过notFull和notEmpty更细腻的控制锁。

     -- 若某线程(线程A)要取出数据时,队列正好为空,则该线程会执行notEmpty.await()进行等待;当其它某个线程(线程B)向队列中插入了数据之后,会调用notEmpty.signal()唤醒“notEmpty上的等待线程”。此时,线程A会被唤醒从而得以继续运行。 此外,线程A在执行取操作前,会获取takeLock,在取操作执行完毕再释放takeLock。
     -- 若某线程(线程H)要插入数据时,队列已满,则该线程会它执行notFull.await()进行等待;当其它某个线程(线程I)取出数据之后,会调用notFull.signal()唤醒“notFull上的等待线程”。此时,线程H就会被唤醒从而得以继续运行。 此外,线程H在执行插入操作前,会获取putLock,在插入操作执行完毕才释放putLock。

 

4、访问一个网址,回车之后的运行机制如何

  客户端在地址栏输入一个URL,会先利用DNS服务获取域名对应的IP地址,然后使用HTTP协议生成针对目标Web服务器的HTTP请求报文,在传输层,TCP协议将HTTP报文分割成报文段,并把每个报文段可靠地传给接收端,在网络层(IP协议),增加作为通信目的地的MAC地址后转发给链路层;接收端的服务器在链路层接收到数据,按序往上层发送,一直到应用层,才算接收到HTTP请求报文,此时HTTP协议对Web服务器请求的内容处理;处理结果同样利用TCP/IP通信协议向用户进行回传。

5、lock、重入锁,独占锁

  AQS--AbstractQueuedSynchronizer类,是Java中管理锁的抽象类,锁的许多公共方法都是在这个类中实现。AQS是独占锁和共享锁的公共父类。

  AQS锁的类别

  (1)独占锁:锁在一个时间点只能被一个线程锁占有。根据锁的获取机制,它又划分为公平锁和非公平锁。公平锁,是按照CLH等待线程按照先来先得的规则,公平的获取锁;而非公平锁,则当线程要获取锁时,它会无视CLH等待队列而直接获取锁。典型:ReentrantLock、ReentrantReadWriteLock.WriteLock;

  (2)共享锁:能被多个线程同时拥有,能被共享的锁。ReentrantReadWriteLock.ReadLock;

  CLH队列:是AQS中“等待锁”的线程队列。在多线程中,为了保护竞争资源不被多个线程同时操作而出现错误,通常需要锁来保护。在独占锁中,竞争资源在一个时间点只能被一个线程锁访问;而其他线程则需要等待。CLH就是管理这些“等待锁”的线程的队列。CLH是一个非阻塞的FIFO队列,也就是说往里面插入或移除一个结点的时候,在并发条件下不会阻塞,而是通过自旋锁和CAS保证结点插入和移除的原子性。

  CAS函数:是比较交换函数,它是原子操作,即通过CAS操作的数据都是以原子方式进行的。

  ReentrantLock是一个可重入的互斥锁,又被称为“独占锁”;ReetrantLock锁在同一个时间点只能被一个线程锁持有,可重入的意思是,ReetrantLock锁可以被单个线程多次获取。ReentrantLock分为“公平锁”和“非公平锁”。它们的区别体现在获取锁的机制上是否公平。“锁”是为了保护竞争资源,防止多个线程同时操作线程而出错,ReentrantLock在同一个时间点只能被一个线程获取(当线程获取到“锁”时,其他线程必须等待);ReentrantLock是通过一个FIFO的等待队列来管理获取该锁所有线程的。在公平锁机制下,线程依次排队获取锁;而非公平锁在锁是可获取状态时,不管自己是不是在队列开头都会获取锁。

  ReentrantLock()默认是非公平锁。非公平锁和公平锁在获取锁的方法上,流程是一样的;它们的区别主要表现在“尝试获取锁的机制不同”。简单点说,“公平锁”在每次尝试获取锁时,都是采用公平策略(根据等待队列依次排序等待);而“非公平锁”在每次尝试获取锁时,都是采用的非公平策略(无视等待队列,直接尝试获取锁,如果锁是空闲的,即可获取状态,则获取锁)。

  公平锁

  获取锁是通过lock()函数,lock()在ReentrantLock.java的FairSync类中实现。“当前线程”实际上是通过acquire(1)获取锁的,“1”是设置锁的状态的参数。对于独占锁而言,锁处于可获取状态时,它的状态值是0;锁被线程初次获取到了,它的状态值就变成了1.由于ReentrantLock是可重入锁,所以独占锁可以被单个线程多次获取,没过去一次就将锁的状态+1.也就是说,初次获取锁时,通过acquire(1)将锁的状态值设为1;再次获取锁时,将锁的状态值设为2;一次类推...

  acquire()在AQS中实现。(1)当前线程首先通过tryAcquire()尝试获取锁,获取成功的话,直接返回;尝试失败的话,进入到等待队列排序等待(前面还有可能有需要线程在等待该锁)(2)当前线程尝试失败的情况下,先通过addWaiter(Node.EXCLUSIVE)来将当前线程加入到CLH队列(非阻塞的FIFO队列)末尾。CLH队列就是线程等待队列。(3)在执行完addWaiter(Node.EXCLUSIVE)之后,会调用acquireQueued()来获取锁。由于此时ReentrantLock是公平锁,它会根据公平性原则来获取锁。(4)当前线程在执行acquireQueued()时,会进入到CLH队列中休眠等待,直到获取锁了才返回。如果当前线程在休眠等待过程中被中断过,acquireQueued会返回true,此时当前线程会调用selfInterrupt()来给自己产生一个中断。

  释放锁是通过unclock()函数,通过AQS的release(1)函数来实现,没释放一次,锁的状态就-1;release()会先调用tryRelease()来尝试释放当前线程锁持有的锁。成功的话,则唤醒后继等待线程,并返回true。否则,直接返回false。

  非公平锁

  非公平锁和公平锁在获取锁的方法上,流程是一样的;它们的区别主要表现在“尝试获取锁的机制不同”。简单点说,“公平锁”在每次尝试获取锁时,都是采用公平策略(根据等待队列依次排序等待);而“非公平锁”在每次尝试获取锁时,都是采用的非公平策略(无视等待队列,直接尝试获取锁,如果锁是空闲的,即可获取状态,则获取锁)。

  非公平锁和公平锁在释放锁的方法和策略上是一样的。

6、对NOSQL了解多少,MYSQL默认的是什么?

  Redis是NoSQL数据库(非关系型数据库),MySQL的数据引擎是InnoDB

posted @ 2018-09-07 15:47  菠菜汤圆  阅读(586)  评论(0编辑  收藏  举报