抽象类和接口有什么区别
接口是公开的,里面不能有私有的方法或变量,是用于让别人使用的,而抽象类是可以有私 有方法或私有变量的, 另外,实现接口的一定要实现接口里定义的所有方法,而实现抽象类可以有选择地重写需要 用到的方法,一般的应用里,最*的是接口,然后是抽象类实现接口,最后才到具体类实 现。 还有,接口可以实现多重继承,而一个类只能继承一个超类,但可以通过继承多个接口实现 多重继承,接口还有标识(里面没有任何方法,如Remote接口)和数据共享(里面的变量 全是常量)的作用。说说自定义注解的场景及实现
(此题*发挥,就看你对注解的理解了!==)登陆、权限拦截、日志处理,以及各种Java 框架,如Spring,Hibernate,JUnit 提到注解就不能不说反射,Java自定义注解是通过运行 时靠反射获取注解。实际开发中,例如我们要获取某个方法的调用日志,可以通过 AOP(动态代理机制)给方法添加切面,通过反射来获取方法包含的注解,如果包含日志 注解,就进行日志记录。HTTP 请求的 GET 与 POST 方式的区别
GET方法会把名值对追加在请求的URL后面。因为URL对字符数目有限制,进而限制了用在 客户端请求的参数值的数目。并且请求中的参数值是可见的,因此,敏感信息不能用这种方 式传递。 POST方法通过把请求参数值放在请求体中来克服GET方法的限制,因此,可以发送的参数 的数目是没有限制的。最后,通过POST请求传递的敏感信息对外部客户端是不可见的。 参考:https://www.cnblogs.com/wangli66/p/5453507.htmlsession 与 cookie 区别
cookie 是 Web 服务器发送给浏览器的一块信息。浏览器会在本地文件中给每一个 Web 服 务 器存储 cookie。以后浏览器在给特定的 Web 服务器发请求的时候,同时会发送所有为该服 务器存储的 cookie。下面列出了 session 和 cookie 的区别: 无论客户端浏览器做怎么样的设置,session都应该能正常工作。客户端可以选择禁用 cookie,但是, session 仍然是能够工作的,因为客户端无法禁用服务端的 session。HashMap 和 Hashtable 的区别
1.hashMap去掉了HashTable 的contains方法,但是加上了containsValue()和 containsKey()方法。 2.hashTable同步的,而HashMap是非同步的,效率上逼hashTable要高。 3.hashMap允许空键值,而hashTable不允许。 注意: TreeMap:非线程安全基于红黑树实现。TreeMap没有调优选项,因为该树总处于平衡状 态。 Treemap:适用于按自然顺序或自定义顺序遍历键(key)。 参考:http://blog.csdn.net/qq_22118507/article/details/51576319HashSet 和 HashMap 区别
set是线性结构,set中的值不能重复,hashset是set的hash实现,hashset中值不能重复是 用hashmap的key来实现的。map是键值对映射,可以空键空值。HashMap是Map接口的hash实现,key的唯一性是通过 key值hash值的唯一来确定,value值是则是链表结构。 他们的共同点都是hash算法实现的唯一性,他们都不能持有基本类型,只能持有对象HashMap 和 ConcurrentHashMap 的区别
ConcurrentHashMap是线程安全的HashMap的实现。 (1)ConcurrentHashMap对整个桶数组进行了分割分段(Segment),然后在每一个分段上 都用lock锁进行保护,相对于HashTable的syn关键字锁的粒度更精细了一些,并发性能更 好,而HashMap没有锁机制,不是线程安全的。 (2)HashMap的键值对允许有null,但是ConCurrentHashMap都不允许。说说线程安全问题
线程安全是指要控制多个线程对某个资源的有序访问或修改,而在这些线程之间没有产生冲 突。在Java里,线程安全一般体现在两个方面: 1、多个thread对同一个java实例的访问( read和modify)不会相互干扰,它主要体现在关 键字synchronized。如ArrayList和Vector,HashMap和Hashtable(后者每个方法前都有 synchronized关键字)。如果你在interator一个List对象时,其它线程remove一个element, 问题就出现了。 2、每个线程都有自己的字段,而不会在多个线程之间共享。它主要体现在 java.lang.ThreadLocal类,而没有Java关键字支持,如像static、transient那样。Session 分布式方案
1.客户端cookie加密。(一般用于内网中企业级的系统中,要求用户浏览器端的cookie不能 禁用,禁用的话,该方案会失效)。 2.集群中,各个应用服务器提供了session复制的功能,tomcat和jboss都实现了这样的功 能。特点:性能随着服务器增加急剧下降,容易引起广播风暴;session数据需要序列化, 影响性能。3.session的持久化,使用数据库来保存session。就算服务器宕机也没事儿,数据库中的 session照样存在。特点:每次请求session都要读写数据库,会带来性能开销。使用内存数 据库,会提高性能,但是宕机会丢失数据(像支付宝的宕机,有同城灾备、异地灾备)。 4.使用共享存储来保存session。和数据库类似,就算宕机了也没有事儿。其实就是专门搞 一台服务器,全部对session落地。特点:频繁的进行序列化和反序列化会影响性能。 5.使用memcached来保存session。本质上是内存数据库的解决方案。特点:存入 memcached的数据需要序列化,效率极低。final, finally, finalize 的区别
1. final 修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作 为父类被继承。因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或 方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时 给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使 用,不能重载。 2. finally 在异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)。 3. finalize 方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前 做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象 调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方 法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前 对这个对象调用的。Spring MVC 运行流程
1.用户发送请求到DispatchServlet 2.DispatchServlet根据请求路径查询具体的Handler 3.HandlerMapping返回一个HandlerExcutionChain给DispatchServlet HandlerExcutionChain:Handler和Interceptor集合 4.DispatchServlet调用HandlerAdapter适配器 5.HandlerAdapter调用具体的Handler处理业务 6.Handler处理结束返回一个具体的ModelAndView给适配器 ModelAndView:model–>数据模型,view–>视图名称 7.适配器将ModelAndView给DispatchServlet 8.DispatchServlet把视图名称给ViewResolver视图解析器 9.ViewResolver返回一个具体的视图给DispatchServlet 10.渲染视图 11.展示给用户怎么唤醒一个阻塞的线程
如果线程是因为调用了 wait()、sleep()或 者 join()方法而导致的阻塞,可以中断线程,并且通过抛出 InterruptedException 来唤醒它;如果线程遇到了 IO 阻塞,无能为力,因为 IO 是操作系统实现的,Java 代码并没有办法直接接触到操作系统。
不可变对象对多线程有什么帮助
前面有提到过的一个问题,不可变对象保证了对象的内存可见性,对不可变对象的读取不需要进行额外的同步手段,提升了代码执行效率。
什么是多线程的上下文切换
多线程的上下文切换是指 CPU 控制权由一个已经正在运行的线程切换到另外一个就绪并等待获取 CPU 执行权的线程的过程。
如果你提交任务时,线程池队列已满,这时会发生什么
这里区分一下:
(1)如果使用的是*队列 LinkedBlockingQueue,也就是*队列的话,没关系,继续添加任务到阻塞队列中等待执行,因为 LinkedBlockingQueue 可以近乎认为是一个无穷大的队列,可以无限存放任务
(2)如果使用的是有界队列比如 ArrayBlockingQueue,任务首先会被添加到ArrayBlockingQueue 中,ArrayBlockingQueue 满了,会根据maximumPoolSize 的值增加线程数量,如果增加了线程数量还是处理不过来,ArrayBlockingQueue 继续满,那么则会使用拒绝策略RejectedExecutionHandler 处理满了的任务,默认是 AbortPolicy
Java 中用到的线程调度算法是什么
抢占式。一个线程用完 CPU 之后,操作系统会根据线程优先级、线程饥饿情况等数据算出一个总的优先级并分配下一个时间片给某个线程执行。
什么是线程调度器(Thread Scheduler)和时间分片(TimeSlicing)?
线程调度器是一个操作系统服务,它负责为 Runnable 状态的线程分配 CPU 时间。一旦我们创建一个线程并启动它,它的执行便依赖于线程调度器的实现。时间分片是指将可用的 CPU 时间分配给可用的 Runnable 线程的过程。分配 CPU 时间可以基于线程优先级或者线程等待的时间。线程调度并不受到 Java 虚拟机控制,所以由应用程序来控制它是更好的选择(也就是说不要让你的程序依赖于线程的优先级)。
什么是自旋
很多 synchronized 里面的代码只是一些很简单的代码,执行时间非常快,此时等待的线程都加锁可能是一种不太值得的操作,因为线程阻塞涉及到用户态和内核态切换的问题。既然 synchronized 里面的代码执行得非常快,不妨让等待锁的线程不要被阻塞,而是在 synchronized 的边界做忙循环,这就是自旋。如果做了多次忙循环发现还没有获得锁,再阻塞,这样可能是一种更好的策略。
Java Concurrency API 中的 Lock 接口(Lock interface)是什么?对比同步它有什么优势?
Lock 接口比同步方法和同步块提供了更具扩展性的锁操作。他们允许更灵活的结构,可以具有完全不同的性质,并且可以支持多个相关类的条件对象。
它的优势有:
(1)可以使锁更公平
(2)可以使线程在等待锁的时候响应中断
(3)可以让线程尝试获取锁,并在无法获取锁的时候立即返回或者等待一段时间
(4)可以在不同的范围,以不同的顺序获取和释放锁
单例模式的线程安全性
老生常谈的问题了,首先要说的是单例模式的线程安全意味着:某个类的实例在多线程环境下只会被创建一次出来。单例模式有很多种的写法,我总结一下:
(1)饿汉式单例模式的写法:线程安全
(2)懒汉式单例模式的写法:非线程安全
(3)双检锁单例模式的写法:线程安全
Semaphore 有什么作用
Semaphore 就是一个信号量,它的作用是限制某段代码块的并发数。Semaphore有一个构造函数,可以传入一个 int 型整数 n,表示某段代码最多只有 n 个线程可以访问,如果超出了 n,那么请等待,等到某个线程执行完毕这段代码块,下一个线程再进入。由此可以看出如果 Semaphore 构造函数中传入的 int 型整数 n=1,相当于变成了一个 synchronized 了。