赞
踩
结论:equals 相等的 hashcode一定相等,反之不一定。
**原因:**在java中,equals和hashcode是有设计要求的,equals相等,则hashcode一定相等,反之则不然。
为何会有这样的要求?
在集合中,比如HashSet中,要求放入的对象不能重复
,怎么判定呢?
首先
会调用hashcode,如果hashcode相等,则继续调用equals
,也相等,则认为重复。如果重写equals后,如果不重写hashcode,则hashcode就是继承自Object
的,返回内存编码,这时候可能出现equals相等,而hashcode不等
,你的对象使用集合时,就会等不到正确的结果
。
hashmap 和hashtable基本上一样,只不过hashtable是线程安全的
,而hashmap 是线程不安全的。而concurrenthashtable跟hashtable的区别在于,concurrenthashtable
是基于用了分段锁的设计
,只有在同一个分段内才存在竞态关系
,不同的分段锁之间没有锁竞争。相比于对整个Map加锁的设计,分段锁大大的提高了高并发环境下的处理能力
。但同时,由于不是对整个Map加锁,导致一些需要扫描整个Map的方法(如size(), containsValue())需要使用特殊的实现,另外一些方法(如clear())甚至放弃了对一致性的要求(ConcurrentHashMap是弱一致性的
,具体请查看ConcurrentHashMap能完全替代HashTable吗?)。
hashmap底层是数组加链表
结构,数组用来根据key的hashcode值来定位一个对象应该属于哪一个index,而链表结构可以解决当key的hashcode值相等而equals方法值不相等的问题。,而treemap底层是红黑树结构
,红黑树的结构是为了兼顾增删改查的多维度性能而设计的。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
默认保留线程数量
,即便是线程是空闲线程。最大数量
的线程。空闲情况下最长保留时间
。存储等待执行的任务
,包括:ArrayBlockingQueue(有界阻塞队列,在队列达到一定),LinkedBlockingQueue,SynchronousQueue,其中LinkedBlockingQueue(链表阻塞队列,包括了读锁和写锁,而ArrayBlockingQueue只有一个锁,所以效率相对LinkedBlockingQueue会慢一些)和SynchronousQueue(同步阻塞队列,它没有容器,生产之后就需要有消费者来消费)比较常用。ThreadLocal 底层是存储在 线程本地Map里面的一个对象,它跟当前线程绑定,以 ThreadLocal 对象本身为 key,以ThreadLocal里面存的值为值,目的是为了实现线程之间的数据的隔离。
public static final ThreadLocal session = new ThreadLocal();
public static Session getCurrentSession() {
Session s = (Session)session.get();
if(s == null){
s = sessionFactory.openSession();
session.set(s);
}
return s;
}
##8、volatile的工作原理?
线程安全需要3步骤:
1.操作的原子性(要么全部成功,要不全部失败)
2.操作的可见性(所有线程都可见)
3.操作的有序性。而对于volatile的只能保证可见性,所以对于 i=i++这种操作是不具有原子性的,所以这类的操作无法使用 volatile关键字进行修饰。
使用场景:
volatile boolean shutdownRequested;
...
public void shutdown() {
shutdownRequested = true;
}
public void doWork() {
while (!shutdownRequested) {
// do stuff
}
}
package com.masterslave.singleton; /** * 双重检查 */ public class DoubleCheck { /** * 因为instance被声明成了 volatile 所以, * 每次得到的对象都是主内存中最新的对象状态,所以保证了实例的可见性 */ private volatile static DoubleCheck instance; private DoubleCheck() { } /** * 双重检查保证线程安全 * @return */ public static DoubleCheck getInstance() { if(instance == null) { synchronized (instance) { if (instance == null) { instance = new DoubleCheck(); } } } return instance; } }
如下代码展示了身份验证机制如何记忆最近一次登录的用户的名字。将反复使用lastUser 引用来发布值,以供程序的其他部分使用。
public class UserManager {
public volatile String lastUser; //发布的信息
public boolean authenticate(String user, String password) {
boolean valid = passwordIsValid(user, password);
if (valid) {
User u = new User();
activeUsers.add(u);
lastUser = user;
}
return valid;
}
}
如果读操作远远超过写操作,您可以结合使用内部锁和 volatile 变量来减少公共代码路径的开销。
@ThreadSafe
public class CheesyCounter {
// Employs the cheap read-write lock trick
// All mutative operations MUST be done with the 'this' lock held
@GuardedBy("this") private volatile int value;
//读操作,没有synchronized,提高性能
public int getValue() {
return value;
}
//写操作,必须synchronized。因为x++不是原子操作
public synchronized int increment() {
return value++;
}
Compare and Swap 比较并刷新到缓存。通过比较线程旧值跟内存中的值是否相等来判断当前的值能否刷新到缓存中。
饿汉模式:
package com.masterslave.singleton; /** * 饿汉模式 */ public class Hungry { private static Hungry instance = new Hungry(); private Hungry() { } public static Hungry getInstance() { return instance; } }
懒汉模式
package com.masterslave.singleton; /** * 懒汉模式 */ public class Lazy { private static Lazy instance; private Lazy() { } /** * 使用 synchronized 解决线程安全问题 * @return */ synchronized public static Lazy getInstance() { if(instance == null) { instance = new Lazy(); } return instance; } }
双重检查
package com.masterslave.singleton; /** * 双重检查 */ public class DoubleCheck { /** * 因为instance被声明成了 volatile 所以, * 每次得到的对象都是主内存中最新的对象状态,所以保证了实例的可见性 */ private volatile static DoubleCheck instance; private DoubleCheck() { } /** * 双重检查保证线程安全 * @return */ public static DoubleCheck getInstance() { if(instance == null) { synchronized (instance) { if (instance == null) { instance = new DoubleCheck(); } } } return instance; } }
静态内部类
package com.masterslave.singleton; /** * 静态内部类 */ public class InnerStaticClass { static class InnerClass{ /** * 由于静态单例对象没有作为 InnerStaticClass 的成员变量直接实例化, * 因此类加载时不会实例化 instance 对象, * 第一次调用 getInstance 时将加载内部类 InnerClass, * 在该类内部定义了一个 instance 变量,此时首先会初始化这个变量, * 由java虚拟机来保证线程安全性,确保改成员变量只能实例化一次, * 由于没有任何锁定,所以其性能不会受到任何影响。 */ private final static InnerStaticClass instance = new InnerStaticClass(); } private InnerStaticClass() { } public static InnerStaticClass getInstance() { return InnerClass.instance; } }
几种模式性能比较:
jvm包括2方面:
1.1.线程私有区:
1.程序计数器,记录正在执行的虚拟机字节码的地址。
2.虚拟机栈:方法执行的内存区,每个方法执行时会在虚拟机栈中创建栈帧。
3.本地方法栈:虚拟机的Native方法执行的内存区。
1.2.线程共享区:
1.Java堆:对象分配内存的区域;
2.方法区:也称为持久代
3.常量池:存放编译器生成的各种字面量和符号引用,是方法区的一部分。
full gc 需要先定位然后找出问题之后再具体解决,比如使用visualvm 工具先定位出现问题的原因,在jvm参数上配置如下参数,在发生full GC之前先把堆内容给备份一下。
-Xmx2g -XX:+HeapDumpBeforeFullGC
-XX:HeapDumpPath=. -Xloggc:gc.log
-XX:+PrintGC -XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=10
-XX:GCLogFileSize=100m
-XX:HeapDumpOnOutOfMemoryError
import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.WritableByteChannel; public class MyClassLoader extends ClassLoader { public MyClassLoader() { } public MyClassLoader(ClassLoader parent) { super(parent); } protected Class<?> findClass(String name) throws ClassNotFoundException { File file = new File("D:/People.class"); try{ byte[] bytes = getClassBytes(file); //defineClass方法可以把二进制流字节组成的文件转换为一个java.lang.Class Class<?> c = this.defineClass(name, bytes, 0, bytes.length); return c; } catch (Exception e) { e.printStackTrace(); } return super.findClass(name); } private byte[] getClassBytes(File file) throws Exception { // 这里要读入.class的字节,因此要使用字节流 FileInputStream fis = new FileInputStream(file); FileChannel fc = fis.getChannel(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); WritableByteChannel wbc = Channels.newChannel(baos); ByteBuffer by = ByteBuffer.allocate(1024); while (true){ int i = fc.read(by); if (i == 0 || i == -1) break; by.flip(); wbc.write(by); by.clear(); } fis.close(); return baos.toByteArray(); } }
你可以动态地安装、卸载、启动、停止不同的应用模块,而不需要重启容器。
##6、请问你做过哪些JVM优化?使用什么方法达到什么效果?
##7、classforName(“java.lang.String”)和String classgetClassLoader() LoadClass(“java.lang.String”) 什么区别啊?
Class.forName() 会初始化对象,而String.class.getClassLoader 不会。
Class.forName(className)方法,内部实际调用的方法是Class.forName(className,true,classloader);
第2个boolean参数表示类是否需要初始化, Class.forName(className)默认是需要初始化
。
一旦初始化,就会触发目标对象的 static块代码执行,static参数也也会被再次初始化
。
ClassLoader.loadClass(className)方法,内部实际调用的方法是 ClassLoader.loadClass(className,false);
第2个 boolean参数,表示目标对象是否进行链接,false表示不进行链接,由上面介绍可以,不进
行链接意味着不进行包括初始化等一些列步骤
,那么静态块和静态对象就不会得到执行。
#Spring
##1、spring都有哪些机制啊AOP底层如何实现的啊IOC呢?
<aop:aspectj-autoproxy proxy-target-class="true"/>)。
##1、使用mysq索引都有哪些原则? 索引什么数据结构?
1.MyISAM存储引擎:不支持事务、也不支持外键,优势是访问速度快,对事务完整性没有 要求或者以select,insert为主的应用基本上可以用这个引擎来创建表
2.该存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全。但是对比MyISAM引擎,写的处理效率会差一些,并且会占用更多的磁盘空间以保留数据和索引。
InnoDB存储引擎的特点:支持自动增长列,支持外键约束
原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。
隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
持久性(Durability):一个事务一旦提交,他对数据库的修改应该永久保存在数据库中。
#分库分表
##1、如何设计可以动态扩容缩容的分库分表方案?
##2、用过哪些分库分表中间件,有啥优点和缺点?讲一下你了解的分库分表中间件的底层实现原理?
##3、我现在有一个未分库分表的系统,以后系统需分库分表,如何设计,让未分库分表的系统动态切换到分库分表的系统上? 那若出现网络原因,网络连不通怎么办啊?
##4、分布式事务知道吗? 你们怎么解决的?
##5、为什么要分库分表啊???
##6、分布式寻址方式都有哪些算法知道一致性hash吗?手写一下java实现代码??你若userId取摸分片,那我要查一段连续时间里的数据怎么办???
##7、如何解决分库分表主键问题有什么实现方案??
主键不采用自增策略,而采用统一主键生成规则。
#分布式缓存
##1、redis和memcheched 什么区别为什么单线程的redis比多线程的memched效率要高啊?
相同点:都是使用的多路io复用的方式,减少了阻塞,充分的利用cpu和内存性能。
不同点:redis单进程单线程,Memcache 多进程单线程,redis自己写了一套epoll的实现,而Memcache 使用的是Libevent,这个组件本身比较大,有很多无用代码,对Memcache性能有影响,还有就是Memcache采用的CAS这种方式也会对性能造成影响。
##2、redis有什么数据类型都在哪些场景下使用啊?
##3、reids的主从复制是怎么实现的redis的集群模式是如何实现的呢redis的key是如何寻址的啊?
1.全量同步
Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份。具体步骤如下:
1)从服务器连接主服务器,发送SYNC命令;
2)主服务器接收到SYNC命名后,开始执行BGSAVE命令生成RDB文件并使用缓冲区记录此后执行的所有写命令;
3)主服务器BGSAVE执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令;
4)从服务器收到快照文件后丢弃所有旧数据,载入收到的快照;
5)主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令;
6)从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;
2.增量同步
Redis
Slave初始化后开始正常工作时
主服务器发生的写操作同步到从服务器的过程。
增量复制的过程主要是主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令。
主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。当然,如果有需要,slave 在任何时候都可以发起全is 策略是,无论如何,首先会尝试进行增量同步,如不成功,要求从机进行全量同步。
如果多个Slave断线了,需要重启的时候,因为只要Slave启动,就会发送sync请求和主机全量同步,当
多个同时出现的时候,可能会导致Master IO剧增宕机
。
##4、使用redis如何设计分布式锁?使用zk可以吗?如何实现啊这两种哪个效率更高啊??
##5、知道redis的持久化吗都有什么缺点优点啊? ?具体底层实现呢?
##6、redis过期策略都有哪些LRU 写一下java版本的代码吧??
#分布式服务框架
##1、说一下dubbo的实现过程注册中心挂了可以继续通信吗??
##2、zk原理知道吗zk都可以干什么Paxos算法知道吗?说一下原理和实现??
##3、dubbo支持哪些序列化协议?hessian 说一下hessian的数据结构PB知道吗为啥PB效率是最高的啊??
##4、知道netty吗’netty可以干嘛呀NIO,BIO,AIO 都是什么啊有什么区别啊?
##5、dubbo复制均衡策略和高可用策略都有哪些啊动态代理策略呢?
##6、为什么要进行系统拆分啊拆分不用dubbo可以吗’dubbo和thrift什么区别啊?
#分布式消息队列
##1、为什么使用消息队列啊消息队列有什么优点和缺点啊?
##2、如何保证消息队列的高可用啊如何保证消息不被重复消费啊
##3、kafka ,activemq,rabbitmq ,rocketmq都有什么优点,缺点啊???
##4、如果让你写一个消息队列,该如何进行架构设计啊?说一下你的思路
#分布式搜索引擎
##1、es的工作过程实现是如何的?如何实现分布式的啊
##2、es在数据量很大的情况下( 数十亿级别)如何提高查询效率啊?
##3、es的查询是一个怎么的工作过程?底层的lucence介绍一下呗倒排索引知道吗?es和mongdb什么区别啊都在什么场景下使用啊?
#高并发高可用架构设计
##1、如何设计一个高并发高可用系统
##2、如何限流?工程中怎么做的,说一下具体实现
##3、缓存如何使用的缓存使用不当会造成什么后果?
##4、如何熔断啊?熔断框架都有哪些?具体实现原理知道吗?
##5、如何降级如何进行系统拆分,如何数据库拆分???
#分布式专题架构
通信协议
##1、说一下TCP 'IP四层?
##2、http的工作流程?? ?http1.0 http1.1http2.0 具体哪些区别啊?
##3、TCP三次握手,四层分手的工作流程画一下流程图为什么不是四次五次或者二次啊?
##4、画一下https的工作流程?具体如何实现啊?如何防止被抓包啊??
算法
##1、比较简单,我一个文件,有45亿个阿拉伯数字,如何进行去重啊如何找出最大的那个数啊?
数据结构
##1、二叉树和红黑树等。
源码中所用到的经典设计思想用设计模式
及常用设计模式
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。