说说String与StringBuffer、StringBuilder的区别?

String是字符串常量,StringBuffer、StringBuilder是字符串变量。
每次对String进行值的修改的时候都会产生一个新的字符串对象,StringBuffer、StringBuilder不会产生新对象。
StringBuilder重在提升性能,在多线程环境下不安全、StringBuffer是线程安全的,性能较StringBuilder差。
当业务场景需要对字符串频繁进行修改的时候,最好使用 StringBuffer 和 StringBuilder 类。

你怎么理解cookie和session,有哪些不同点?

由于HTTP是一种无状态的协议,Session和Cookie就是为解决这个问题而诞生的会话跟踪技术。
session是基于cookie实现的。
cookie存储在客户端浏览器且可以伪造不安全,session存储在服务器端相对安全。
session使用相对灵活可以是任意对象,cookie只能是字符串。
cookie有体积大小(各浏览器的限制不同)的限制,session理论上没有。
session过多存储会消耗服务器存储资源,cookie不会。

java事件机制包括哪三个部分?请分别介绍

事件、事件监听器、事件源。
事件类,用于封装事件源及一些与事件相关的参数。
事件监听器,用于重写回调方法,将事件触发的处理逻辑定义在重写的回调方法中。
事件源,也就是事件被触发的地方。

redis支持的数据类型有哪些?

string、hash键值对、list按照插入顺序排序、set无序、zset去重/排序。

悲观锁和乐观锁的区别

悲观锁一碰数据就上锁阻塞按序执行,时间及性能上会有所牺牲,但保证了数据安全,不适合高并发的场景。synchronized和ReentrantLock就是悲观锁。
乐观锁追求性能及响应速度,不轻易加锁。

多线程有哪几种实现方法?同步有哪几种实现方法

继承Thread类、实现Runnable接口、线程池实现多线程。
synchronized等jvm锁和分布式锁、wait与notify、CountDownLatch等juc包下的同步容器能实现同步方法。

谈谈你对线程池的理解,以及线程池的优化

线程池通过对线程的复用从而降低线程的创建和销毁带来的性能开销。
优点有以下几个角度:降低资源消耗/提高响应速度/提高线程的可管理性。
常见用法有:Executors.newSingleThreadExecutor()单线程可以实现任务的有序执行;newFixedThreadPool线程大小固定/newCachedThreadPool可缓存/newScheduledThreadPool大小最大为Integer.MAX_VALUE实现定时调度需求。
优化从使用场景来讲:一般应用分为计算密集型、IO密集型以及两者混合的。
计算密集型:要充分压榨CPU资源合理计算线程数,一般为Runtime.availableProcessors+1。
IO密集型:执行IO操作时,CPU处于等待状态,等待过程中操作系统会把CPU时间片分给其他线程,可以使用newCachedThreadPool优化。
两者混合型:根据任务等待阻塞时间与CPU计算时间的比重来决定线程数量。
总之就是合理设置线程数量。

为什么wait,notify和notifyAll是在Object类中定义的而不是在Thread类中定义?

这些方法存在于同步场景中,也就是wait,notify和notifyAll都是锁级别的操作,但是锁可以是任意对象,所以任意对象调用方法一定定义在Object类中。

为什么TCP建立连接协议是三次握手,而关闭连接却是四次握手呢?为什么不能用两次握手进行连接?

建立一个连接需要三次握手,而终止一个连接要经过 4次握手。是由TCP的半关闭(half -close)造成的。一个TCP连接是全双工(即数据在两个方向上能同时传递),因此每个方向必须单独地进行关闭。

如何理解内存泄漏问题?有哪些情况会导致内存泄漏?如何解决?

(https://www.jb51.net/article/92311.htm)
内存泄漏是指不再使用的对象持续占有内存或无用对象的内存得不到及时释放,从而造成内存空间的浪费称为内存泄漏。
Java中内存泄漏的发生场景:
静态集合类引起内存泄漏;当集合里面的对象属性被修改后,再调用remove()方法时不起作用;监听器未及时删除;各种连接如数据库连接网络连接等未准确close;内部类和外部模块的引用等。

zookeeper负载均衡和nginx负载均衡的区别

nginx的其中一个主要功能就是用做反向代理服务器,内置了负载均衡相关的算法,但是随着节点的增加导致配置维护成本及单点故障的风险增加增加。ZooKeeper作为一个服务的注册中心,服务调用者能按照zk提供所需服务的服务器列表,然后自己根据负载均衡算法,从中选取一台服务器进行连接。由于ZooKeeper并没有内置负载均衡策略,需要调用者自己实现,这个方案只是利用了ZooKeeper的树形数据结构、watcher机制等特性,把ZooKeeper作为服务的注册和变更通知中心,解决了Nginx负载均衡方案带来的问题。

说说dubbo服务暴露的过程

首先将服务的实现封装成一个Invoker,Invoker中封装了服务的实现类。
将Invoker封装成Exporter,并缓存起来,缓存里使用Invoker的url作为key。
服务端Server启动,监听端口。请求来到时,根据请求信息生成key,到缓存查找Exporter,就找到了Invoker,就可以完成调用。

程序运算结果(一)

package com.zxl;

class HelloA {
    public HelloA() {
        System.out.println("HelloA");
    }

    {
        System.out.println("I'm A class");
    }

    static {
        System.out.println("static A");
    }

}

public class HelloB extends HelloA {
    public HelloB() {
        System.out.println("HelloB");
    }

    {
        System.out.println("I'm B class");
    }

    static {
        System.out.println("static B");
    }

    public static void main(String[] args) {
        new HelloB();
    }

}

结果:
static A
static B
I’m A class
HelloA
I’m B class
HelloB

程序运行结果(二)

package com.zxl;

public class Example {

    String str = new String("good");

    char[] ch = {'a', 'b', 'c'};

    public static void main(String args[]) {

        Example ex = new Example();
        ex.change(ex.str, ex.ch);

        System.out.print(ex.str + " and ");

        System.out.print(ex.ch);

    }

    public void change(String str, char ch[]) {

        str = "test ok";

        ch[0] = 'g';

    }
}

结果:
good and gbc

利用一个3升的桶和一个5升的桶,如何量出4升水?

将5升桶倒满。
把5升桶的水倒满3升桶,剩下2升水。
将3升桶的水倒光。
把5升桶里剩下的2升水倒入3升桶。
将5升桶倒满。
把5升桶的水倒入3升桶至满。
此时5升桶里刚好剩下有4升。

如下图所示,警察先走,警察能不能抓到小偷?请简述

qd面试题及答案_面试

如果前提条件是警察走一步,小偷必须也走一步的话,可以按如下走法抓到小偷:
step1:警察走左下,小偷只能左上;
step2:警察往右一步,小偷只能左下;
step3:警察左上回到开局位置,小偷此时往上往下都会被抓;
step4:警察抓住小偷。
如果小偷不是非得走的话,警察抓不到小偷。