java基础面试题总结(2)—— JDK基础

2018-08-15  本文已影响5人  天渊hyominnLover

JAVA SE基础

1.ArrayList、LinkedList、Vector的特性及存储性能(持续更新)

2.HashMap、Hashtable、ConcurrentHashMap、LinkedHashMap(持续更新)

3.简述JVM内存结构中的heap和stack(持续更新)

4.GC是什么? 为什么要有GC?

5.关于String的知识点

  1. String s = new String("xyz"); 创建了几个String Object? :
    创建了2个String对象,首先传入的"xyz"是一个String对象,然后new的过程又创建了一个String对象

6.abstract的方法是否可以是static的?是否可以是synchronized的?

7.lock与Synchronize的区别?lock的基本使用方法及特性(持续更新)

        final void lock() {
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }

可以看出,首先采用CAS机制来修改对象头中的锁标志位,CAS机制有三个重要参数:内存位置(V)、预期原值(A)和新值(B), 其中0就是期望的标志位原值A,1就是期望的标志位新值B;最终会调用一个native方法compareAndSwapInt()来使用CPU的CAS机制进行CAS操作,来不断尝试获取锁

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 阻塞栈,用于存放Mantou对象
 */
public class SyncStack {
    volatile int index = 0;//栈内当前Mantou数量,需保证线程可见
    Lock lock = new ReentrantLock();//初始化锁
    Condition condition = lock.newCondition();//初始化Condition对象用于线程间通信
    Mantou[] mantous;

    public SyncStack(int size) {
        //初始化栈内容器的大小
        mantous = new Mantou[size];
    }

    /**
     * 将Mantou放入栈中,每放一个,index就增加一个,然后将等待池中的线程唤醒
     * 执行该方法前若检测若index已满则执行await,执行push()的线程进入Lock的等待池
     * @param mantou
     */
    public void push(Mantou mantou){
        //获取同步锁
        lock.lock();
        try{
            while(index == this.mantous.length){
                condition.await();
            }
            this.mantous[index] = mantou;
            index++;
            condition.signalAll();
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    /**
     * 将栈顶的Mantou拿出来,每拿一个,index就减少一个,然后将等待池中的线程唤醒
     * 执行该方法前若检测index为空则执行await,执行get()的线程进入Lock等待池
     * @return
     */
    public Mantou get(){
        lock.lock();
        try{
            while(index == 0){
                //设置等待时间,一旦超时就返回false,退出该方法
                if(!condition.await(30, TimeUnit.SECONDS)){
                    return null;
                }
            }
            index--;
            condition.signalAll();
            return this.mantous[index];
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
        return null;
    }
}
public class Mantou {
    int id;
    String owner;
    public Mantou(int id, String owner){
        this.id = id;
        this.owner = owner;
    }

    @Override
    public String toString() {
        return owner + "的" +String.valueOf(id);
    }
}
/**
 * 生产者线程,持续调用push方法向阻塞栈放入Mantou对象
 */
public class Producer implements Runnable{
    SyncStack syncStack;
    public Producer(SyncStack syncStack) {
        this.syncStack = syncStack;
    }
    @Override
    public void run() {
        //持续放入8个Mantou
        for(int i = 0; i<8; i++){
            Mantou mantou = new Mantou(i, Thread.currentThread().getName());
            syncStack.push(mantou);
            System.out.println(Thread.currentThread().getName()+":生产了" + mantou + "号馒头!!!");
            try{
                Thread.sleep(1000);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}
/**
 * 消费者线程,持续调用get方法从阻塞栈取出Mantou对象
 */
public class Consumer implements Runnable{
    SyncStack syncStack;
    public Consumer(SyncStack syncStack) {
        this.syncStack = syncStack;
    }
    @Override
    public void run() {
        Mantou mantou;
        //一旦获取Mantou超时,则退出
        while((mantou = syncStack.get())!=null) {
            System.out.println(Thread.currentThread().getName() + ":拿到了" + mantou + "号馒头!!!");
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName() + ":靠!居然没有了!艹!走了!");
    }
}

测试:

    public static void main(String[] args){
        SyncStack syncStack = new SyncStack(10);
        Consumer consumer = new Consumer(syncStack);
        Producer producer = new Producer(syncStack);
        Thread consumerThread1 = new Thread(consumer);
        Thread consumerThread2 = new Thread(consumer);
        Thread consumerThread3 = new Thread(consumer);
        Thread producerThread1 = new Thread(producer);
        Thread producerThread2 = new Thread(producer);
        consumerThread1.setName("消费者1");
        consumerThread2.setName("消费者2");
        consumerThread3.setName("消费者3");
        producerThread1.setName("生产者甲");
        producerThread2.setName("生产者已");
        producerThread1.start();
        producerThread2.start();
        consumerThread1.start();
        consumerThread2.start();
        consumerThread3.start();

跟传统的wait和notifyAll方式大同小异

8. 反射中Class.forName()和ClassLoader.loadClass()的区别

反射中,Class.forName()和ClassLoader的方法loadClass()都可以通过类名加载类并返回类的Class对象,但是两者有一些区别:

上一篇 下一篇

猜你喜欢

热点阅读