高级java工程师面经总结(更新中)

2019-11-21  本文已影响0人  _Rondo

前言:最近在面高级,总结一些需要知道的知识,一边在面一边在写,欢迎补充

一、java 基础

1.基本数据类型
数据类型 字节长度 类型
byte 1 整型
shot 2 整型
int 4 整型
long 8 整型
float 4 浮点型
double 8 浮点型
boolean - 布尔型
char 2 字符型

String 是java中特殊的类,用来接收字符串,String的常量池和Integer的IntegerCache异曲同工,关于String 有兴趣的朋友可以看看这篇https://www.cnblogs.com/zhangyinhua/p/7689974.html

        String a = "a";
        String b = new String("a");
        String c = "a";
        //入常量池
        String d = new String("a").intern();
        System.out.println(a == b);//false
        System.out.println(a == c);//true
        System.out.println(a == d);//true

        Integer integer = 17;
        Integer integer1 = 17;
        System.out.println(integer == integer1);//true
        Integer integer2 = 128;
        Integer integer3 = 128;
        System.out.println(integer2 == integer3);//false
2.特性

①基本特性
封装:属性、方法的封装
多态:就是一个类中同名的方法不同参数和返回值
继承:选择题比较多,主要涉及父类中的方法重写,和父类静态属性和方法不能重写

②高级特性
反射:运行状态中获取类的名和方法,对象也是;可以延伸出静态、动态代理的比较,也会有手写动态代理的简答题,关于反射和代理看下这两篇
https://www.cnblogs.com/yueshutong/p/9495001.html
https://www.cnblogs.com/maohuidong/p/7992894.html

//静态代理 示例,可以参考下SpringContextHolder
public interface Job {
    void testJob();
}
public class JobImpl implements Job{
    @Override
    public void testJob() {
        System.out.println("静态job");
    }
}
public class Proxy implements Job{

    private Job job;

    @Override
    public void testJob() {
        init();
        job.testJob();
    }

    private void init(){
        if(job == null){
            job = new JobImpl();
        }
    }

    public static void main(String[] args) {
        new Proxy().testJob();
    }
}


//动态代理示例
public interface Job {
    void doSomething();
}
public class JobImpl implements Job{

    @Override
    public void doSomething() {
        System.out.println("动态job");
    }
}
public class MyProxy implements InvocationHandler {

    private Job job;

    public MyProxy(Job j){
        this.job = j;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object object = method.invoke(job,args);
        return object;
    }

    public Object getProxyInstance(){
        return Proxy.newProxyInstance(job.getClass().getClassLoader(),job.getClass().getInterfaces(),this);
    }
}
public class Test {
    public static void main(String[] args) {
        Job job = new JobImpl();
        MyProxy proxy = new MyProxy(job);
        Job job1 = (Job) proxy.getProxyInstance();
        job1.doSomething();
    }
}

泛型:只会作用于编译时期,指定数据类型,可能会问下?通配符
类型转换:回考察一些自动转换、强制转换的计算和编译问题
序列化:可能以前做xml解析的时候还能被问到,现在都是json了没怎么被问
注解:类、方法、变量、参数和包等都可以被标注,获取到的时候配合拦截
器做逻辑,和python、js的装饰器不太一样

//注解示例
@Target(value = {ElementType.FIELD,ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Hello {
    String value();
}

@Hello("hello")
public static void main(String[] args) throws NoSuchMethodException {
    Class cls = Test.class;
    Method method = cls.getMethod("main", String[].class);
    Hello hello = method.getAnnotation(Hello.class);    
}
3.集合(可问点很多)
关系图

看下这篇https://www.cnblogs.com/jing99/p/7057245.html

①Collection型,存储单个key

②map型,以key-value形式进行存储;

4.并发编程

①java内存模型

//synchronized 
public class TestSync {
    public static void main(String[] args) {
        final TestSync test = new TestSync();
        // 线程1
        new Thread(() -> {
                test.get(Thread.currentThread());
        }).start();
        // 线程2
        new Thread(() -> {
                test.get(Thread.currentThread());
        }).start();
    }

    public synchronized void get(Thread thread) {
        long start = System.currentTimeMillis();
        int i = 0;
        while(System.currentTimeMillis() - start <= 1) {
            i++;
            if(i % 4 == 0) {
                System.out.println(thread.getName() + "正在进行写操作");
            } else {
                System.out.println(thread.getName() + "正在进行读操作");
            }
        }
        System.out.println(thread.getName() + "读写操作完毕");
    }
}

//Lock
public class TestLock {

    private ReentrantReadWriteLock rwl  = new ReentrantReadWriteLock();

    public static void main(String[] args) {

        final TestLock lock = new TestLock();

        new Thread(() -> {
            lock.get(Thread.currentThread());
            lock.write(Thread.currentThread());
        }).start();

        new Thread(() -> {
            lock.get(Thread.currentThread());
            lock.write(Thread.currentThread());
        }).start();
    }

    /**
     * 读操作,用读锁锁定
     * @param thread
     */
    public void get(Thread thread) {
        boolean bool = rwl.readLock().tryLock();
        if(bool){
            try {
                long start = System.currentTimeMillis();
                while(System.currentTimeMillis() - start <= 1) {
                    System.out.println(thread.getName() + "正在进行读操作");
                }
                System.out.println(thread.getName() + "读操作完毕");
            } catch (Exception e) {

            } finally {
                rwl.readLock().unlock();
            }
        }

    }
    /**
     * 写操作,用写锁来锁定
     * @param thread
     */
    public void write(Thread thread) {
        boolean bool = rwl.writeLock().tryLock();
        if(bool){
            try {
                long start = System.currentTimeMillis();
                while(System.currentTimeMillis() - start <= 1) {
                    System.out.println(thread.getName() + "正在进行写操作");
                }
            } catch (Exception e) {

            } finally {
                rwl.writeLock().unlock();
            }
        }
    }
}
public class FinalExample {
    int i;                            //普通变量
    final int j ;                      //final变量
    static FinalExample obj;

    public FinalExample(int j) {
        this.j = j;
    }

    public void FinalExample () {     //构造函数
        i = 1;                             //写final域
    }

    public static void writer(int j,Thread thread) {    //写线程A执行
        obj = new FinalExample (j);
        System.out.println(thread.getName()+"  写入: "+j);
    }

    public static void reader(Thread thread) {       //读线程B执行
        FinalExample object = obj;       //读对象引用
        int a = object.i;                //读普通域
        int b = object.j;                //读final域
        System.out.println(thread.getName()+"  读出 :"+b);
    }
}

public class Test {
    public static void main(String[] args) {
        int num = 2;

        new Thread(() -> {
            FinalExample.writer(num, Thread.currentThread());
        }).start();

        new Thread(() -> {
            FinalExample.reader(Thread.currentThread());
        }).start();

    }
}

③线程
看看这篇https://www.cnblogs.com/wxd0108/p/5479442.html

④生产者-消费者的三种实现方式,看下这篇https://blog.csdn.net/a491857321/article/details/79262996

⑤线程池:

//简单线程池示例
public interface ThreadPool <Job extends Runnable>{

    //执行一个Job,job需要实现Runnable
    void execute(Job job);

    //关闭线程池
    void shutdown();

    //增加工作者线程
    void addWorkers(int nums);

    //减少工作者线程
    void removeWorkers(int nums);

    //得到正在工作的线程数
    int getJobSize();
}

public class DefaultThreadPool <Job extends Runnable> implements ThreadPool<Job> {

    //最大工作者线程数
    private static final int MAX_WORKERS_NUMS = 10;
    //默认工作者线程数
    private static final int DEFAULT_WORKERS_NUMS = 5;
    //最小工作者线程数
    private static final int MIN_WORKERS_NUMS = 1;
    //工作列表
    private final LinkedList<Job> jobs = new LinkedList<Job>();
    //工作者线程
    private final List<Worker> workers = Collections.synchronizedList(new ArrayList<>());

    private int workerNums = DEFAULT_WORKERS_NUMS;

    private AtomicLong threadNum = new AtomicLong();

    public DefaultThreadPool(int workerNums) {
        int workNums = workerNums > MAX_WORKERS_NUMS ? MAX_WORKERS_NUMS :
                workerNums < MIN_WORKERS_NUMS ? MIN_WORKERS_NUMS : workerNums;
        initializaWorkers(workNums);
    }


    public DefaultThreadPool() {
        initializaWorkers(DEFAULT_WORKERS_NUMS);
    }

    private void initializaWorkers(int workerNums) {
        for(int i = 0; i < workerNums; i++) {
            Worker worker = new Worker();
            Thread thread = new Thread(worker, "WorkNumble" + threadNum.incrementAndGet());
            thread.start();
        }
    }

    @Override
    public void execute(Job job) {
        if(job == null) {
            synchronized (jobs) {
                jobs.addLast(job);
                jobs.notify();
            }
        }
    }

    @Override
    public void shutdown() {
        for(Worker worker : workers) {
            worker.showdown();
        }
    }

    @Override
    public void addWorkers(int nums) {
        synchronized (jobs) {
            if(nums + this.workerNums > MAX_WORKERS_NUMS)
                nums = MAX_WORKERS_NUMS - nums;
            initializaWorkers(nums);
            this.workerNums += nums;
        }
    }

    @Override
    public void removeWorkers(int nums) {
        synchronized (jobs) {
            if(nums >= this.workerNums) {

            }
            int count = 0;
            while(count < nums) {
                Worker worker = workers.get(count);
                if(workers.remove(worker)) {
                    worker.showdown();
                    count++;
                }
            }
            this.workerNums -= count;
        }
    }

    @Override
    public int getJobSize() {
        return jobs.size();
    }

    class Worker implements Runnable{

        volatile private boolean running = true;

        @Override
        public void run() {
            while(running) {
                Job job = null;
                synchronized (jobs) {
                    while(jobs.isEmpty()) {
                        try {
                            jobs.wait();
                        }catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                            return ;
                        }
                    }
                    job = jobs.removeFirst();
                }
                if(job != null) {
                    try {
                        job.run();
                    }catch (Exception e) {

                    }
                }
            }
        }

        public void showdown() {
            running  = false;
        }

    }
}

⑥连接池:可能回会一下等待超时模型

//连接池简单示例
public class ConnectionPool {

    private LinkedList<Connection> pool = new LinkedList<Connection>();

    public ConnectionPool(int initialSize) {
        if (initialSize > 0) {
            for (int i = 0; i < initialSize; i++) {
                pool.addLast(ConnectionDriver.createConnection());
            }
        }
    }

    public void releaseConnection(Connection connection) {
        if (connection != null) {
            synchronized (pool) {
                // 连接释放后需要进行通知,这样其他消费者能够感知到连接池中已经归还了一个连接
                pool.addLast(connection);
                pool.notifyAll();
            }
        }
    }// 在mills内无法获取到连接,将会返回null

    public Connection fetchConnection(long mills) throws InterruptedException {
        synchronized (pool) {
            // 完全超时
            if (mills <= 0) {
                while (pool.isEmpty()) {
                    pool.wait();
                }
                return pool.removeFirst();
            } else {
                long future = System.currentTimeMillis() + mills;
                long remaining = mills;
                while (pool.isEmpty() && remaining > 0) {
                    pool.wait(remaining);
                    remaining = future - System.currentTimeMillis();
                }
                Connection result = null;
                if (!pool.isEmpty()) {
                    result = pool.removeFirst();
                }
                return result;
            }
        }
    }
}
public class ConnectionDriver {
    static class ConnectionHandler implements InvocationHandler {
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (method.getName().equals("commit")) {
                TimeUnit.MILLISECONDS.sleep(100);
            }
            return null;
        }
    }// 创建一个Connection的代理,在commit时休眠100毫秒

    public static final Connection createConnection() {
        return (Connection) Proxy.newProxyInstance(ConnectionDriver.class.getClassLoader(),
                new Class<?>[] { Connection.class }, new ConnectionHandler());
    }
}
public class ConnectionPoolTest {
    static ConnectionPool pool = new ConnectionPool(10);
    // 保证所有ConnectionRunner能够同时开始
    static CountDownLatch start = new CountDownLatch(1);
    // main线程将会等待所有ConnectionRunner结束后才能继续执行
    static CountDownLatch end;

    public static void main(String[] args) throws Exception {
        // 线程数量,可以修改线程数量进行观察
        int threadCount = 10;
        end = new CountDownLatch(threadCount);
        int count = 20;
        AtomicInteger got = new AtomicInteger();
        AtomicInteger notGot = new AtomicInteger();
        for (int i = 0; i < threadCount; i++) {
            Thread thread = new Thread(new ConnetionRunner(count, got, notGot), "ConnectionRunnerThread");
            thread.start();
        }
        start.countDown();
        end.await();
        System.out.println("total invoke: " + (threadCount * count));
        System.out.println("got connection: " + got);
        System.out.println("not got connection " + notGot);
    }

    static class ConnetionRunner implements Runnable {
        int count;
        AtomicInteger got;
        AtomicInteger notGot;

        public ConnetionRunner(int count, AtomicInteger got, AtomicInteger notGot) {
            this.count = count;
            this.got = got;
            this.notGot = notGot;
        }

        public void run() {
            try {
                start.await();
            } catch (Exception ex) {
            }
            while (count > 0) {
                try {
                    // 从线程池中获取连接,如果1000ms内无法获取到,将会返回null
                    // 分别统计连接获取的数量got和未获取到的数量notGot
                    Connection connection = pool.fetchConnection(1000);
                    if (connection != null) {
                        try {
                            connection.createStatement();
                            connection.commit();
                        } finally {
                            pool.releaseConnection(connection);
                            got.incrementAndGet();
                        }
                    } else {
                        notGot.incrementAndGet();
                    }
                } catch (Exception ex) {
                } finally {
                    count--;
                }
            }
            end.countDown();
        }
    }
}

⑦Fork/Join:将一个线程拆分到几个几个线程中并行计算结果

//斐波那契 forkjoin
public class RecursiveTaskDemo {

    private static class Fibonacci extends RecursiveTask<Integer> {

        final int n;

        public Fibonacci(int n) {
            this.n = n;
        }

        @Override
        protected Integer compute() {
            if (n <= 1) {
                return n;
            }else {
                Fibonacci f1 = new Fibonacci(n - 1);
                f1.fork();
                Fibonacci f2 = new Fibonacci(n - 1);
                return f2.compute() + f1.join();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ForkJoinPool pool = new ForkJoinPool();
        Future<Integer> future = pool.submit(new Fibonacci(10));
        System.out.println(future.get());
        pool.shutdown();
    }
}

⑧并发容器和Executor(书没看完,暂时不写)

5.IO

①IO
io操作数据流和数组,两者可以相互转换,字节流继承inputstream,outputstream;字符流继承Writer,Reader,目前还没被问到,下面是关系图


image.png

②NIO 是一种同步非阻塞的I/O模型,也是I/O多路复用的基础,包括buffer、channel、selector,写过通讯其实很好理解。

③AIO 异步非阻塞的I/O模型(没用过暂时不写)

6.JVM

①JVM组成

②四种引用

③GC(还没看明白待完善)
④优化(没做过暂时不写)

二、Spring

1.spring bean

就是先编写一个XML文件,然后使用Spring框架了来读取这个配置文件就可以使用这个bean,有时候会问springbean 和 java bean 区别

2.AOP/IOC
3.spring 事务
4.springmvc 执行流程:

1.用户发送出请求到前端控制器DispatcherServlet。
2.DispatcherServlet收到请求调用HandlerMapping(处理器映射器)。
3.HandlerMapping找到具体的处理器(可查找xml配置或注解配置),生成处理器对象及处理器拦截器(如果有),再一起返回给DispatcherServlet。
4.DispatcherServlet调用HandlerAdapter(处理器适配器)。
5.HandlerAdapter经过适配调用具体的处理器(Handler/Controller)。
6.Controller执行完成返回ModelAndView对象。
7.HandlerAdapter将Controller执行结果ModelAndView返回给DispatcherServlet。
8.DispatcherServlet将ModelAndView传给ViewReslover(视图解析器)。
9.ViewReslover解析后返回具体View(视图)。
10.DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11.DispatcherServlet响应用户。

5.spring 中的设计模式

1.简单工厂又叫做静态工厂方法(StaticFactory Method)
2.工厂方法(Factory Method)
3.单例模式(Singleton)
4.适配器(Adapter)
5.包装器(Decorator)
6.代理(Proxy)
7.观察者(Observer)
8.策略(Strategy)
9.模板方法(Template Method)

三、计算机组成原理/网络

1.OSI七层协议模型、TCP/IP四层模型和五层协议体系结构之间的关系

看下这篇https://www.cnblogs.com/wxd0108/p/7597216.html

image.png
2.TCP/IP和UDP
3.HTTP

超文本传输协议

三、DB/SQL

1.关系型DB(mysql)

①索引
②优化

2.NoSQL

①redis
②memcache
③mongodb

四、服务器/容器

1.Linux
2.Docker(入门级别,欢迎指导)

五、分布式/MQ

1.分布式理论-CAP/BASE
2.分布式锁原理及实现方式
3.分布式事务
4.JMS/MQTT

六、数据结构/算法

1.数组/链表/队列
2.树
3.堆栈
3.算法

①选择/冒泡排序
②递归
③快速排序

七、Git

八、WEB前端

1.DOM
2.JavaScript

九、安卓

1.四大组件

十、大数据

1.hadoop、pig
2.hbase

十一、值得看的题目

1.sql
2.算法

十二、没想到吧还有发散思维题

上一篇 下一篇

猜你喜欢

热点阅读