1、HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。 HashMap底层就是一个数组结构,数组中的每一项又是一个链表。当新建一个HashMap的时候,就会初始化一个数组。
2、以前看过,10
3、List:1.可以允许重复的对象。 2.可以插入多个null元素。 3.是一个有序的容器,保持了每个元素的插入顺序,输出顺序就是插入顺序。 4.常用的实现类有 ArrayList、LinkedList 和 Vector。ArrayList 最为流行,它提供了使用索引的随意访问,而 LinkedList 则对于经常需要从 List 中添加或删除元素的场合更为合适。
Set:1.不允许重复对象。 2.无需容器,你无法保证每个元素的存储顺序,TreeSet通过Comparator或者Comparable维护了一个排序顺序。 3.只允许一个null元素。 4.Set接口最流行的几个实现类HashSet、LinkedHashSet、以及TreeSet。最流行的是基于HashMap实现的HashSet;TreeSet还实现了SortedSet接口,因此TreeSet是一个根据其compare()和compareTo()的定义今昔排序的有序容器。
4、vlolatile是一个特殊的的修饰符,和synchronize同步锁差不多,只能修饰成员变量,在Java并发程序缺少同步类的情况下,多线程对成员变量的操作对其他线程是透明的。volatilel变量可以保证下一个读取操作会在前一个写操作之后发生。
5、进程:是并发执行的程序在执行过程中分配和管理资源的基本单位。 线程:是进程的一个执行单元,线程也被称为轻量级进程。 区别:①同一进程的线程共享本进程的地址空间,而进程之间则是独立的地址空间。 ②同一进程内的线程共享本进程的资源,如:内存、I/O、cpu等,但是进程之间的资源是独立的。 ③一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮。 ④进程切换时,消耗的资源大,效率高。所以涉及到频繁的切换时,使用线程要好于进程。同样如果要求同时进行并且又要共享某些变量的并发操作,只能用线程不能用进程。 ⑤每个独立的进程程有一个程序运行的入口、顺序执行序列和程序入口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。 ⑥线程是处理器调度的基本单位,但是进程不是。 ⑦两者均可并发执行。 对资源的管理和保护要求高,不限制开销和效率时,使用多进程。 要求效率高,频繁切换时,资源的保护管理要求不是很高时,使用多线程。
6、优化数据库的方法:①选取适用的字段属性。(数据库中的表越小,在它上面执行的查询也就会越快。因此,在创建表的时候,为了获得更好的性能,我们可以将表中字段的宽度设得尽可能小。) ②使用连接(JOIN)来代替子查询(Sub-Queries)。 ③使用联合(UNION)来代替手动创建的临时表。 ④事务。(它的作用是:要么语句块中每条语句都操作成功,要么都失败。换句话说,就是可以保持数据库中数据的一致性和完整性。事物以BEGIN关键字开始,COMMIT关键字结束。在这之间的一条SQL操作失败,那么,ROLLBACK命令就可以把数据库恢复到BEGIN开始之前的状态。 事务的另一个重要作用是当多个用户同时使用相同的数据源时,它可以利用锁定数据库的方法来为用户提供一种安全的访问方式,这样可以保证用户的操作不被其它的用户所干扰。) ⑤锁定表。(由于在事务执行的过程中,数据库将会被锁定,因此其它的用户请求只能暂时等待直到该事务结束。如果一个数据库系统只有少数几个用户来使用,事务造成的影响不会成为一个太大的问题;但假设有成千上万的用户同时访问一个数据库系统,就会产生比较严重的响应延迟。) ⑥使用外键。(锁定表的方法可以维护数据的完整性,但是它却不能保证数据的关联性。这个时候我们就可以使用外键。) ⑦使用索引。(索引是提高数据库性能的常用方法,它可以令数据库服务器以比没有索引快得多的速度检索特定的行,尤其是在查询语句当中包含有MAX(),MIN()和ORDERBY这些命令的时候,性能提高更为明显。 一般说来,索引应建立在那些将用于JOIN,WHERE判断和ORDERBY排序的字段上。尽量不要对数据库中某个含有大量重复的值的字段建立索引。) ⑧优化的查询语句。(绝大多数情况下,使用索引可以提高查询的速度,但如果SQL语句使用不恰当的话,索引将无法发挥它应有的作用。)
7、①synchronized是java内置关键字,在jvm层面,Lock是个java类。 ②synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁。 ③synchronized会自动释放锁(a 线程执行完同步代码会释放锁 ;b 线程执行过程中发生异常会释放锁),Lock需在finally中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁。 ④用synchronized关键字的两个线程1和线程2,如果当前线程1获得锁,线程2线程等待。如果线程1阻塞,线程2则会一直等待下去,而Lock锁就不一定会等待下去,如果尝试获取不到锁,线程可以不用一直等待就结束了。 ⑤synchronized的锁可重入、不可中断、非公平,而Lock锁可重入、可判断、可公平(两者皆可) ⑥Lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少量的同步问题。
8、高并发:它通常是指,通过设计保证系统能够同时并行处理很多请求。高并发相关常用的一些指标有响应时间(Response Time),吞吐量(Throughput),每秒查询率QPS(Query Per Second),并发用户数等。 提高系统并发能力的方式,方法论上主要有两种:垂直扩展(Scale Up)与水平扩展(Scale Out)。 垂直扩展:提升单机处理能力。垂直扩展的方式又有两种:①增强单机硬件性能,如:增加CPU核数、升级网卡,硬盘、扩充硬盘容量和系统内存等。 ②提升单机架构性能,如:使用Cache来减少IO次数,使用异步来增加单服务吞吐量,使用无锁数据结构来减少响应时间。 单机性能总是有极限的。所以互联网分布式架构设计高并发终极解决方案还是水平扩展。 水平扩展:只要增加服务器数量,就能线性扩充系统性能。 ①反向代理层的水平扩展:反向代理层可以通过“DNS轮询”的方式来进行水平扩展。 ②站点层的水平扩展:站点层可以通过nginx来进行水平扩展。 ③服务层的水平扩展:服务层可以通过服务连接池来进行水平扩展。 ④数据层的水平扩展:数据库可以按照数据范围,或者数据哈希的方式来进行水平扩展。 各层实施水平扩展后,能够通过增加服务器数量的方式来提升系统的性能,做到理论上的性能无限。
9、==是一个比较运算符,基本数据类型比较的是值,引用数据类型比较的是地址值。(比较地址值即是指是否为同一个对象的引用) equals()是一个方法,只能比较引用数据类型。重写前比较的是地址值,重写后比一般是比较对象的属性。 ==是判断两个变量或实例是不是指向同一个内存空间(是判断两个对象是否是同一个对象)
equals是判断两个变量或实例所指向的内存空间的值是不是相同(是进行值的判断)
10、关于String的:String、StringBuffer、StringBuilder他们之间的区别? String是Java中基础且重要的类,被声明的变量,一旦被声明就不可改变,除非重新new一个String对象,容易造成内存浪费。 StringBuffer:被创建的对象可变,线程安全,但是速度较慢。 StringBuilder:和StringBuffer差不多,二者都继承了 AbstractStringBuilder,但是StringBuilder是线程不安全的,所以StringBuilder速度较快。 ①在字符串不经常发生变化的业务场景优先使用String(代码更清晰简洁)。 ②在单线程情况下,如有大量的字符串操作情况,应该使用StringBuilder来操作字符串。 ③在多线程情况下,如有大量的字符串操作情况,应该使用StringBuffer。
11、不能。但是删除倒数第二个元素是不会报错。
12、能,但不能多继承。继承是所有OOP语言不可缺少的部分,在java中使用extends关键字来表示继承关系。当创建一个类时,总是在继承,如果没有明确指出要继承的类,就总是隐式地从根类Object进行继承。
区别:①接口里面没有:变量、普通方法、构造器! ②接口中的变量 只能是静态常量 系统默认加上public static final; ③接口中的方法 默认都是public abstract修饰的;--------