面试题整理

2020-01-09  本文已影响0人  白茫茫的大地

数组实现队列

public class ArrayQueue {

    private String [] items;  //定义数组
    private int n = 0;           //数组大小
    private int head = 0;     //表示队头下标
    private int tail = 0;        //表示队尾下标

    //申请一个大小为capacity的数组
    public ArrayQueue(int capacity) {
        this.n = capacity;
        this.items = new String[capacity];  //初始化数组
    }

    public boolean enQueue(String item) {
        if (tail == n) {  //队列已经满了
            return false;
        }
        items[tail] = item;
        tail++;
        return true;
    }

    public String deQueue() {
        if (head == tail) {   //队列为空
            return null;
        }
        String item = items[head];
        head++;
        return item;
    }

}
public class ArrayStack {
    String[] arrays;
    int i = 0;

    public ArrayStack(int n) {
        arrays = new String[n];
    }

    public void push(String item) {
        if (i > arrays.length - 1) {
            return;
        }
        arrays[i] = item;
        i++;
    }

    public String pop() {
        if (i > 0) {
            i--;
        }
        String temp = arrays[i];
        arrays[i] = null;
        return temp;
    }

}

java软引用与弱引用区别

参考了一些资料

final变量用反射修改

  1. HashMap的内部结构,给定一个key,如何找到对应的value,使用equal
  2. volatile
  3. Java线程池有什么作用
  4. Java动态代理
  5. handler机制
  6. android跨进程通信的方式
  7. 自定义控件方式
  8. Canvas绘制过什么 手写功能

断点续传的实现

app 启动速度的优化

影响启动的因素
启动耗时检测
解决方案

线程优化

线程调度模型
如何干预线程调度?
Android异步方式
Android线程优化实战
线程收敛优雅实践初步

布局优化

减少过度绘制

导致过度绘制的主要原因是:
如何避免过度绘制

webview的优化

fresco加载图片原理 优势是什么

缓存怎么处理的

a、根据Uri在已解码的(Bitmap缓存)内存缓存中查找,找到了则返回Bitmap对象;如果没找到,则开启后台线程开始后续的工作。
b、根据Uri在未解码的内存缓存中查找,若找到了则解码,然后缓存到已解码的内存缓存中,并且返回Bitmap对象。
d、如果在未解码的内存缓存中没找到,则根据Uri在磁盘缓存中查找,若找到了则读取数据(byte数组),并缓存到未解码的内存缓存中,解码、然后缓存到已解码的内存缓存中,并且返回Bitmap对象。
e、如果在磁盘缓存中没找到,则从网络或者本地加载数据。加载完成后,依次缓存到磁盘缓存、未解码的内存缓存中。解码、然后缓存到已解码的内存缓存中,并且返回Bitmap对象。

bitmap 内存分配

多进程通讯的方式

Handler 如何规避内存泄漏

data binding

Android中动画的原理

字符串hash函数

    public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

ThreadLocal

编码格式

volatile

用于保持内存可见性(随时见到的都是最新值)和防止指令重排序 参考

java内存模型
volatile保持可见性
防止指令重排
  class Singleton {
    private static Singleton instance;
    private Singleton(){}
    public static Singleton getInstance() {
        if ( instance == null ) { //当instance不为null时,仍可能指向一个“被部分初始化的对象”
            synchronized (Singleton.class) {
                if ( instance == null ) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

它可以”抽象“为下面几条JVM指令:

memory = allocate();    //1:分配对象的内存空间
initInstance(memory);   //2:初始化对象
instance = memory;      //3:设置instance指向刚分配的内存地址

JVM可以以“优化”为目的对它们进行重排序,经过重排序后如下:

memory = allocate();    //1:分配对象的内存空间
instance = memory;      //3:设置instance指向刚分配的内存地址(此时对象还未初始化)
ctorInstance(memory);   //2:初始化对象

引用instance指向了一个"被部分初始化的对象"。此时,如果另一个线程调用getInstance方法,由于instance已经指向了一块内存空间,从而if条件判为false,方法返回instance引用,用户得到了没有完成初始化的“半个”单例。

解决这个该问题,只需要将instance声明为volatile变量:

private static volatile Singleton instance;

Thread类的sleep() yield() 和 wait()的区别?

多线程如何保证线程安全

GC

参考

找到被回收的对象
回收算法
分代收集
其他
上一篇 下一篇

猜你喜欢

热点阅读