欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

笔试学习记录4.3

程序员文章站 2022-03-15 19:37:32
...

1、怎样理解一个类是线程安全的?

答:判定一个线程是否安全的基础是在多线程情况下,对一个变量进行操作是否有误差。当多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问,直到该线程读取完,其他线程才可使用。这样是为了防止出现数据不一致或者数据污染的情况。

举例:
比如一个 ArrayList 类,在添加一个元素的时候,它可能会有两步来完成:1. 在 Items[Size] 的位置存放此元素;2. 增大 Size 的值。
在单线程运行的情况下,如果 Size = 0,添加一个元素后,此元素在位置 0,而且 Size=1;
而如果是在多线程情况下,比如有两个线程,线程 A 先将元素存放在位置 0。但是此时 CPU 调度线程A暂停,线程 B 得到运行的机会。线程B也向此 ArrayList 添加元素,因为此时 Size 仍然等于 0 (注意哦,我们假设的是添加一个元素是要两个步骤哦,而线程A仅仅完成了步骤1),所以线程B也将元素存放在位置0。然后线程A和线程B都继续运行,都增加 Size 的值。
那好,我们来看看 ArrayList 的情况,元素实际上只有一个,存放在位置 0,而 Size 却等于 2。这就是“线程不安全”了。

2、Java服务器网络开发时, 请说明通讯中阻塞(blocking)/非阻塞(non-blocking 与 同步/异步IO的区别。

答:
同步/异步主要针对客户端:

    同步:就是当客户端发出一个功能调用时,在没有得到结果之前,该调用就不返回。也就是说必须一件一件的事情去做,等一件做完了才能去做下一件。

     异步:就是当客户端发出一个功能调用时,调用者不用等接收方发出响应。实际处理这个调用的部件在完成后,会通过状态,通知和回调来通知调用者。客户端可以接着去做 后面的事情。

    虽然主要是针对客户端,但是服务器端不是完全没有关系的,同步/异步必须配合服务器端才能实现。同步/异步是由客户端自己控制,但是服务器端是否阻塞/非阻塞,客户端完全不需要关心。

阻塞/非阻塞主要是针对服务器端:

    阻塞:阻塞调用是指服务器端被调用者调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。

    非阻塞:指在不能立即得到结果之前,该调用不会阻塞当前线程。

3、Java常用的数据结构中,请描述Vector, ArrayList, LinkedList的不同场景下的性能差别

答:
Vector 是一个数组结构。但是关键的添加,删除等方法都已经用synchronized修饰,是线程安全的.适合于查询,以及尾部的添加和删除。

vector和数组类似,拥有一段连续的内存空间,并且起始地址不变。因此能高效的进行随机存取,时间复杂度为o(1);但因为内存空间是连续的,所以在进行插入和删除操作时,会造成内存块的拷贝,时间复杂度为o(n)。另外,当数组中内存空间不够时,会重新申请一块内存空间并进行内存拷贝。

连续存储结构:vector是可以实现动态增长的对象数组,支持对数组高效率的访问和在数组尾端的删除和插入操作,在中间和头部删除和插入相对不易,需要挪动大量的数据。它与数组最大的区别就是vector不需程序员自己去考虑容量问题,库里面本身已经实现了容量的动态增长,而数组需要程序员手动写入扩容函数进形扩容。

ArrayList 基于数组存储数据,因此查询元素时可以直接按照数据下标进行索引,而插入元素时,通常涉及到数据元素的复制和移动,所以查询数据快而插入数据慢;线程不安全。

​ LinkedList 基于双向链表存储数据,因此查询元素时需要前向或后向遍历,而插入数据时只需要修改本元素的前后项即可,所以查询数据慢而插入数据快。线程不安全 。、

4、在对数组和链表进行遍历,为什么数组要快一些?

答:
1.首先,数组是具有相同的数据类型且按一定次序排列的一组变量的集合体,构成一个数组的这些变量称为数组元素数组在内存中的地址是连续相邻的,而链表在内存的地址是散列的,不连续的
2. CPU缓存会把一片连续的内存空间读入, 因为数组结构是连续的内存地址, 所以数组全部或者部分元素被连续存 在CPU缓存里面,而链表的节点是分散在堆空间里面的,这时候CPU缓存帮不上忙,只能是去读取内存,而缓存的速率要比内存快。
3. CPU --》寄存器–》缓存 --》内存 cpu 取数据,处理数据,都要放到寄存器中处理(存放指令),缓存就是吧内存中提取的数据暂时保存在里面。如果寄存器要获取内存中同一位置的数据,就从缓存中获取,如果寄存器获取的不是同一个内存地址的数 据(或者获取的内存地址缓存中不存在),就从内存中查找获取
从上述比较中,我们可以看出数组的查询,要比链表的快

相关标签: 面试专栏