300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 最新Java高级程序员架构师面试题及答案

最新Java高级程序员架构师面试题及答案

时间:2024-08-05 20:18:08

相关推荐

最新Java高级程序员架构师面试题及答案

1.Java如何开启线程?怎么保证线程安全?

答:线程与进程的区别:进程是操作系统进行资源分配的最小单元。线程是操作系统进行任务分配的最小单元,线程隶属于进程。

如何开启线程?1. 继承Thread类,重写run方法。2. 实现Runable接口,实现run方法。3. 实现Callable接口,实现call方法。通过FutureTask创建一个线程,获取到线程执行的返回值。4. 通过线程池来开启线程。

怎么保证线程安全?核心思想就是加锁:1. JVM提供的锁,也就是Synchronized关键字。 2. JDK提供的各种锁Lock.

2. Volatile和Synchronized有什么区别?Volatile能不能保证线程安全?DCL(Double Check Lock)单例为什么要加Volatile

答:1. Synchronize关键字,用来加锁,Volatile只是保持亦是的线程可见性。通常适用于一个线程写,多个线程读的场景。

2. Volatile关键字不能保证线程安全,只能保证线程可见性,不能保证原子性。

3.Volatile防止指令重排,在DCL中,防上高并发情况下,指令重排造成的线程安全问题。

3.Java线程锁机制是怎么样的?偏向锁、轻量级锁、重量级锁有什么区别?锁机制是如何升级的?

答:1.Java的锁就是在对象的Markword中记录一个锁状态,无锁、偏向锁、轻量级锁、重量级锁对应不同的锁状态。

2. Java的锁机制就是根据资源竟争的激烈程度不断进行锁升级的过程。

4.谈谈你对AQS的理解。AQS如何实现可重入锁?

答:1. AQS是一个Java线程同步的框架,是JDK中很多锁工具的核心实现框架。

2. 在AQS中,维护了一个信号量state和一个线程组成的双向链表队列,其中,这个线程队列就是用来给线程排队的,而state就像是一个红绿灯,用来控制线程排队或才放行的,在不同的场景下,有不同的意义。

3.在可重入锁这个场景下,state就用来表示加锁的次数,0表示无锁,每加一次锁state就加1,释放锁state就减1.

5.有A、B、C三个线程,如何保证三个线程同时执行?如何在并发情况下保证三个线程依次执行?如何保证三个线程有序交错进行?

答:CountDownLatch,CylicBarrier,Semaphore

public class ThreadSafeDemo {public int count = 0;public void add(){count++;}public static void main(String[] args) throws InterruptedException{int size = 3;ThreadSafeDemo threadSafeDemo = new ThreadSafeDemo();CountDownLatch countDownLatch = new CountDownLatch(1);for(int i=0;i<size;i++){new Thread(()->{try{countDownLatch.await();System.out.println(System.currentTimeMillis());Thread.sleep(100);}catch (Exception ex){ex.printStackTrace();}}).start();}Thread.sleep(5000);countDownLatch.countDown();}}public class OldThread2 {static volatile int tickts = 1;public static void main(String[] args){Thread t1 = new Thread(()->{while (true){if(tickts==1){try {Thread.sleep(100);for(int i=0;i<10;i++){System.out.println("a"+i);}}catch (InterruptedException ie){ie.printStackTrace();}tickts=2;return;}}});Thread t2 = new Thread(()->{while (true){if(tickts==2){try {Thread.sleep(100);for(int i=0;i<10;i++){System.out.println("b"+i);}}catch (InterruptedException ie){ie.printStackTrace();}tickts=3;return;}}});Thread t3 = new Thread(()->{while (true){if(tickts==3){try {Thread.sleep(100);for(int i=0;i<10;i++){System.out.println("c"+i);}}catch (InterruptedException ie){ie.printStackTrace();}tickts=1;return;}}});t1.start();t2.start();t3.start();}}public class OldThread {private static Semaphore s1 = new Semaphore(1);private static Semaphore s2 = new Semaphore(1);private static Semaphore s3 = new Semaphore(1);public static void main(String[] args){try {s1.acquire();s2.acquire();}catch (InterruptedException ex){ex.printStackTrace();}new Thread(()->{while (true){try {s1.acquire();}catch (InterruptedException iex){iex.printStackTrace();}try {Thread.sleep(500);}catch (InterruptedException ex2){ex2.printStackTrace();}System.out.println("A");s2.release();}}).start();new Thread(()->{while (true){try {s2.acquire();}catch (InterruptedException iex){iex.printStackTrace();}try {Thread.sleep(500);}catch (InterruptedException ex2){ex2.printStackTrace();}System.out.println("B");s3.release();}}).start();new Thread(()->{while (true){try {s3.acquire();}catch (InterruptedException iex){iex.printStackTrace();}try {Thread.sleep(500);}catch (InterruptedException ex2){ex2.printStackTrace();}System.out.println("C");s1.release();}}).start();}}

6. 如何对一个字符串快速进行排序?

答:Fork/Join框架

public class MargeTest {private static int MAX = 100;private static int inits[] = new int[MAX];//随机队列初始化static {Random r = new Random();for(int index = 0; index<MAX;index++){inits[index-1] = r.nextInt(1000);}}public static void main(String[] args) throws Exception{long beginTime = System.currentTimeMillis();ForkJoinPool pool = new ForkJoinPool();MyTask task = new MyTask(inits);ForkJoinTask<int[]> taskResult = pool.submit(task);try {int[] ints = taskResult.get();System.out.println(Arrays.toString(ints));}catch (InterruptedException ex){ex.printStackTrace();}long endTime = System.currentTimeMillis();System.out.println("耗时:"+(endTime-beginTime));}static class MyTask extends RecursiveTask<int[]>{private int source[];public MyTask(int source[]){this.source = source;}@Overrideprotected int[] compute() {int sourcelen = source.length;if(sourcelen>2){int midIndex = sourcelen/2;MyTask task1 = new MyTask(Arrays.copyOf(source,midIndex));task1.fork();MyTask task2 = new MyTask(Arrays.copyOfRange(source,midIndex,sourcelen));task2.fork();int result1[] = task1.join();int result2[] = task2.join();int mer[] = joinInts(result1,result2);return mer;}else{if(sourcelen==1 || source[0]<source[1]){return source;}else{int targetTp[] = new int[sourcelen];targetTp[0] = source[1];targetTp[1] = source[0];return targetTp;}}}}}

7. TCP和UDP有什么区别?TCP为什么是三次握手,而不是两次?

答:TCP Transfer Control Protocol 是一种面向连接的,可靠的,传输层通信协议。

特点:好比打电话,面向连接的,点对点的通信,高可靠的,效率比较低,占用的系统资源比较多。

UDP User Datagram Protocol 是一种无连接的,不可靠的,传输层通信协议。

特点:好比广播,不需要连接,发送方不管接收方有没有准备好,直接发消息;可以进行广播发送。传输不可靠,有可能丢失消息;效率比较高,协议比较简单,占用的系统资源比较少。

TCP建立连接三次握手,断开连接四次挥手。如果是两次握手,可能造成连接资源浪费的情况。

8. Java有哪几种IO模型?有什么区别?

答:

BIO 同步阻塞IO。可靠性差,吞吐量低,适用于连接比较少且比较固定的场景。JDK1.4之前唯一的选择。编程模型最简单。

NIO 同步非阻塞IO。可靠性比较好,吞吐量比较高,适用于连接比较多,并且连接比较短(轻操作),例如聊天室,编程模型最复杂。

AIO 异步非阻塞IO。可靠性是最好的,吞吐量也是非常高的,适用于连接比较多,并且连接比较长(重操作)。例如相册服务器。视频流点播等,JDK1.7版本之后提供的。编程模型比较简单,需要操作系统来支持。

同步、异步【针对请求】和阻塞、非阻塞【针对客户端】

在一个网络请求中,客户端会发一个请求到服务端。

1. 客户端发了请求后,就一直等着服务端响应。客户端: 阻塞。 请求:同步

2. 客户端发了请求后,就去干别的事情了,时不时过来检查服务端是否给出了相应。客户端:非阻塞。请求:同步。

3. 换成异步请求。 客户端发了请求后,就坐在椅子上,等着服务端返回响应。客户端:阻塞。 请求:异步。

4. 客户端发了请求后,就去干别的事情了。等到服务端给出响应后,再过来处理业务逻辑。 客户端: 非阻塞。请求:异步。

9.Java NIO的几个核心组件是什么?分别有什么作用?

答:buffer, channel, selector,如下图:

Channel类似于流,每个channel对应一个buffer缓冲区。 channel会注册到selector。selector会根据channel上发生的读写事件,将请求交给某个空闲的线程处理。selector就必然对应一个或者多个线程。buffer和channel都是可读可写的。

10. select,poll和epoll有什么区别?

答:他们是NIO中多路复用的三种实现机制,是由Linux操作系统提供的。

用户空间和内核空间:操作系统为了保护系统安全,将内核划分为两个部分,一个是用户空间,一个是内核空间。用户空间不能直接访问底层的硬件设备,必须通过内核空间。

文件描述符 File Description(FD):是一个抽象的概念,形式上是一个整数,实际上是一个索引值。指向内核中为每个进程维护进程所打开的文件的记录表。当程序打开一个文件或者创建一个文件时,内核就会向进程返回一个FD。Unix,Linux

select机制:会维护一个FD的结合fd_set。将fd_set从用户空间复制到内核空间,激活socket。x64 2048 fd_set是一个数组结构

poll机制:和select机制是差不多的,把fd_set结构进行了优化,FD集合的大小就突破了操作系统的限制。pollfd结构来代替fd_set,通过链表实现的。

epoll机制:event poll,epoll中不再扫描所有的FD,只将用户关心的FD的事件存放到内核的一个事件表当中。这样可以减少用户空间与内核空间之间需要copy的数据。

简单总结:(操作方式) 底层实现 最大连接数 IO效率

select: 遍历 数组 受限于内核 一般

poll 遍历 链表 无上限 一般

epoll 事件回调 红黑树 无上限 高

11. Java的NIO当中是用的那种机制?

可以查看DefaultSelectorProvider源码,在windows下,WindowsSelectorProvider。而Linux下,根据Liunx的内核版本,2.6版本以上,就是EPollSelectorProvider,否则就是默认的PollSelectorProvider

select 1984年出现,poll 1997年出现 epoll 2002年出现

12. 描述下HTTP和HTTPS的区别

答:HTTP是互联网上应用最为广泛的一种网络通信协议。基于TCP,可以使用浏览器工作更为高效,减少网络传输。

HTTPS是HTTP的加强版,可以认为是HTTP+SSL(Secure Socket Layer)。在HTTP的基础上增加了一系列的安全机制。一方面保证数据传输安全,另一方面对访问者增加了验证机制。是目前现行架构下,最为安全的解决方案。

主要区别:

1. HTTP的连接是简单无状态的。HTTPS的数据传输是经过证书加密的,安全性更高。

2. HTTP是免费的,而HTTPS需要申请证书,而证书通常是需要收费的。并且费用一般不低。

3. 他们的传输协议不同,他们使用的端口也是不一样的,HTTP默认是80端口,而HTTPS默认是443端口。

HTTPS的缺点:

1. HTTPS的握手协议比较费时,所以会影响服务的响应速度以及吞吐量。

2. HTTPS也并不是完全安全的,他的证书体系其实并不是完全安全的。并且HTTPS在面对DDOS这样的攻击时,几乎起不到任何作用。

3. 证书需要费钱,并且功能越强大的证书费用越高。

13.说一说JVM的内存模型。

14.JAVA类加载的全过程是怎样的?什么是双亲委派机制?有什么作用?一个对象从加载到JVM,再到被GC清除,都经历了什么过程?

答:Java的类加载机制: AppClassLoader->ExtClassLoader->BootstrapClassLoader

每种类加载器都有他自已的加载目录。

Java中的类加载器:AppClassLoader,ExtClassLoader->URLClassLoader->SecureClassLoader->ClassLoader

每个类加载器对它加载过的类都有一个缓存,

双亲委派:向上委托查找,向下委托加载。作用:保护JAVA底层的类不会被应用程序覆盖。

类加载过程:加载-》连接-》初始化。

加载:通过双亲委派机制把Java的字节码数据加载到JVM内存中,并映射成JVM认可的数据结构。

连接:分为三个小阶段:1.验证:检查加载到的字节信息是否符合JVM规范。2.准备:创建类和接口的静态变量并赋初始值,半初始化状态。3.解析:把符号引用转为直接引用。

1.用户创建一个对象,JVM首先要到方法区去找对象的类型信息,然后创建对象。

2.JVM要实例化一个对象,首先要在堆当中先创建一个对象。-》半初始化状态

3.对象首先会分配在堆内存中的Edon区,然后经过一个Minor GC,对象如果存活,就会进入S区。在后续的每次GC中,如果对象一直存活,就会在S区来分COPY,每移动一次,年龄加1.-》多大年龄才会移入老年代?年龄最大15,超过一定年龄后,对象转入老年代。

4.当方法执行结束后,栈中的指针会先移除。

5.堆中的对象,经过FULL GC,就会被标记为垃圾,然后被GC线程清理掉。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。