Java基础知识面试总结(全面,实时更新)

  sleep和wait区别

1.sleep方法

  属于Thread类中的方法

  释放cpu给其它线程 不释放锁资源

  sleep(1000) 等待超过1s被唤醒

2.wait方法

  属于Object类中的方法

  释放cpu给其它线程,同时释放锁资源

  wait(1000) 等待超过1s被唤醒

  wait() 一直等待需要通过notify或者notifyAll进行唤醒

  wait 方法必须配合 synchronized 一起使用

#### 锁释放时机代码演示
public static void main(String[] args) {
    Object o = new Object();
    Thread thread = new Thread(() -> {
        synchronized (o) {
            System.out.println("新线程获取锁时间:" + LocalDateTime.now() + " 新线程名称:" + Thread.currentThread().getName());
            try {

                //wait 释放cpu同时释放锁
                o.wait(2000);

                //sleep 释放cpu不释放锁
                //Thread.sleep(2000);
                System.out.println("新线程获取释放锁锁时间:" + LocalDateTime.now() + " 新线程名称:" + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    });

    thread.start();

    try {
        Thread.sleep(100);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }

    System.out.println("主线程获取锁时间:" + LocalDateTime.now() + " 主线程名称:" + Thread.currentThread().getName());

    synchronized (o){
        System.out.println("主线程获取释放锁锁时间:" + LocalDateTime.now() + " 主线程名称:" + Thread.currentThread().getName());
    }
}

  ==和equals区别

1.==

如果比较的是基本数据类型,那么比较的是变量的值

如果比较的是引用数据类型,那么比较的是地址值(两个对象是否指向同一块内存)

2.equals

如果没重写equals方法比较的是两个对象的地址值

如果重写了equals方法后我们往往比较的是对象中的属性的内容

equals方法是从Object类中继承的,默认的实现就是使用==

  String buffer和String builde

1.StringBuffer 与 StringBuilder 中的方法和功能完全是等价的,

2.只是StringBuffer 中的方法大都采用了 synchronized 关键字进行修饰,因此是线程安全的,而 StringBuilder 没有这个修饰,可以被认为是线程不安全的。

3.在单线程程序下,StringBuilder效率更快,因为它不需要加锁,不具备多线程安全而StringBuffer则每次都需要判断锁,效率相对更低

  ArrarList和LinkedList区别

1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。

2.对于随机访问get和set,ArrayList效率优于LinkedList,因为LinkedList要移动指针。

3.对于新增和删除操作add和remove,LinkedList比较占优势,因为ArrayList要移动数据。 这一点要看实际情况的。若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList。但若是批量随机的插入删除数据,LinkedList的速度大大优于ArrayList. 因为ArrayList每插入一条数据,要移动插入点及之后的所有数据。

  HashMap底层

hashMap在1.8之前的底层结构是数组+链表,在1.8及以后使用的底层结构式数组+链表+红黑树

他们的区别还有put时的resize()方法的不同。

1.数组 Node[] table ,哈希表,根据对象的key的hash值进行在数组里面是哪个节点

2.链表的作用是解决hash冲突,将hash值取模之后的对象存在一个链表放在hash值对应的槽位

3.红黑树 JDK8使用红黑树来替代超过8个节点的链表,主要是查询性能的提升,从原来的O(n)到O(logn)

4.通过hash碰撞,让HashMap不断产生碰撞,那么相同的key的位置的链表就会不断增长,当对这个Hashmap的相应位置进行查询的时候,就会循环遍历这个超级大的链表,性能就会下降,所以改用红黑树

  HashMap和HashTable区别

1.线程安全性不同

HashMap是线程不安全的,HashTable是线程安全的,其中的方法是Synchronized,在多线程并发的情况下,可以直接使用HashTable,但是使用HashMap时必须自己增加同步处理

2.是否提供contains方法

HashMap只有containsValue和containsKey方法;HashTable有contains、containsKey和containsValue三个方法,其中contains和containsValue方法功能相同。

3.key和value是否允许null值

Hashtable中,key和value都不允许出现null值。HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。

4.数组初始化和扩容机制

HashTable在不指定容量的情况下的默认容量为11,而HashMap为16,Hashtable不要求底层数组的容量一定要为2的整数次幂,而HashMap则要求一定为2的整数次幂,Hashtable扩容时,将容量变为原来的2倍加1,而HashMap扩容时,将容量变为原来的2倍。

  线程的创建方式

1.继承Thread类创建线程

2.实现Runnable接口创建线程

3.使用Callable和Future创建线程   有返回值

4.使用线程池创建线程

#### 代码演示
import java.util.concurrent.*;
public class threadTest{
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //继承thread
        ThreadClass thread = new ThreadClass();
        thread.start();
        Thread.sleep(100);
        System.out.println("#####################");

        //实现runnable
        RunnableClass runnable = new RunnableClass();
        new Thread(runnable).start();
        Thread.sleep(100);
        System.out.println("#####################");

        //实现callable
        FutureTask futureTask = new FutureTask(new CallableClass());
        futureTask.run();
        System.out.println("callable返回值:" + futureTask.get());
        Thread.sleep(100);
        System.out.println("#####################");

        //线程池
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 1, 2, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10));
        threadPoolExecutor.execute(thread);
        threadPoolExecutor.shutdown();
        Thread.sleep(100);
        System.out.println("#####################");

        //使用并发包Executors
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        executorService.execute(thread);
        executorService.shutdown();
    }
}

class ThreadClass extends Thread{
    @Override
    public void run() {
        System.out.println("我是继承thread形式:" + Thread.currentThread().getName());
    }
}

class RunnableClass implements Runnable{
    @Override
    public void run(){
        System.out.println("我是实现runnable接口:" + Thread.currentThread().getName());
    }
}

class CallableClass  implements Callable {
    @Override
    public String call(){
        System.out.println("我是实现callable接口:");
        return "我是返回值,可以通过get方法获取";
    }
}

  Java中有几种类型的流

Java基础知识面试总结(全面,实时更新)_第1张图片

Java基础知识面试总结(全面,实时更新)_第2张图片

你可能感兴趣的:(直面Java,java,开发语言,面试)