2017面试题总结

来源:互联网 发布:社区门诊软件 编辑:程序博客网 时间:2024/06/06 04:20

Wy

1.spring事务,不回滚的事务

2. list map set 的jdk树

3. 如何实现一个classload,有几大加载器,是否可以实现覆盖Integer,String

4. synchronized与lock的区别

5. ==和equals,intern()

6. Sleep wait

7: concurrentHashMap  hashTable 实现线程安全的方式

8. synchronized和lock(有两个实现类)

9. Jvm的类加载器

10. Equals和hashcode


Didi

1. jvm 细看

2. 消费者生产者模式代码

     m1:  BlockingQueue<Product> queues =new LinkedBlockingQueue<Product>(10);  消费者take,生产者put

    LinkedBlockingQueue是一个线程安全的阻塞队列,实现了先进先出等特性,是作为生产者消费者的首选,可以指定容量,也可以不指定,不指定的话默认最大是Integer.MAX_VALUE,其中主要用到put和take方法,put方法将一个对象放到队列尾部,在队列满的时候会阻塞直到有队列成员被消费,take方法从head取一个对象,在队列为空的时候会阻塞,直到有队列成员被放进来。

      m2:    见下方代码

3. 


Wlqc

1. 基本数据类型有哪些

2.synchronized用法

3. 二叉树求最大距离

求数组主元素



回答wy

  1. 看紫色笔记中EJB的事务,spring一样,只是多了nest




----notify  wait 实现消费者生产者-

我踩的坑

坑1: 注意标红的queue,我之前synchronized中写的是queue,但是wait和notify写的是this.wait()和this.notify(),抛异常java.lang.IllegalMonitorStateException

jdk的异常解释是: 抛出的异常表明某一线程已经试图等待对象的监视器,或者试图通知其他正在等待对象的监视器而本身没有指定监视器的线程

也就是说我准备等待的对象是this对象,但是这个this对象上面并没有锁,因为我的锁在queue这个对象上面,所以必须要用queue.wait()!!!!  

一定要注意前后一致!!

  • 也就是当前的线程不是此对象监视器的所有者。也就是要在当前线程锁定对象,才能用锁定的对象此行这些方法,需要用到synchronized ,锁定什么对象就用什么对象来执行

  • notify()notifyAll(),wait()wait(long)wait(long, int)操作,否则就会报IllegalMonitorStateException异常。
    例如 :
    exapmle 1,锁定方法所属的实例对象:
    public synchronized void method(){
        //然后就可以调用:this.notify()...
        //或者直接调用notify()...
    }
    exapmle 2,锁定方法所属的实例的Class:
    public Class Test{
     public static synchronized void method(){
        //然后调用:Test.class.notify()...
     }
    }
    exapmle 3,锁定其他对象:
    public Class Test{
    public Object lock = new Object();
     public static void method(){
        synchronized (lock) {
         //需要调用 lock.notify();
        } 
     }
    }

坑2: 我把sleep放在1 和2 的位置,那么整个消费的顺序不是生产一条消费一条

因为 这两个位置还在监控范围中,没有释放锁,消费者执行不了!!

总结是: 多动手写代码,很简单的一段代码动手写都会收获很多!

package com.bj58.hxx.tool.test;


import java.util.Date;

import java.util.concurrent.ArrayBlockingQueue;


public class ProducerAndConsumer {


private static ArrayBlockingQueue<Date> queue = new ArrayBlockingQueue<Date>(100);

public ProducerAndConsumer() {

}


public static void main(String[] args) {

ProducerAndConsumer pc = new ProducerAndConsumer();

new Thread(pc.new Producer(pc)).start();

new Thread(pc.new Consumer(pc)).start();

}


class Producer implements Runnable{

private ProducerAndConsumer pc;

public Producer(ProducerAndConsumer pc){

this.pc = pc;

}

public void put(){

synchronized(queue){

if(queue.size() >= 100){

try {

queue.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

Date d = new Date();

queue.offer(d);

System.out.println("producer is put "+d);;

                                // 1

queue.notify();

                            // 2

}

try {

Thread.sleep(2000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}


@Override

public void run() {

while(true){

this.put();

}

}

}

class Consumer implements Runnable{

private ProducerAndConsumer pc;

public Consumer(ProducerAndConsumer pc){

this.pc = pc;

}

public void get(){

synchronized(queue){

if(queue.isEmpty()){

try {

queue.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

System.out.println("consumer is get "+queue.poll());;

queue.notify();

}

}


@Override

public void run() {

while(true){

this.get();

}

}

}

}

4.尚德

.快排

.二叉树遍历,不用递归

.数据库引擎,支持事务


从N中选取最大的k个数字,为啥用最小堆,不用最大堆

选用最小堆的步骤是: 先取前k个数字,建立最小堆,这个时候堆顶的数字就是这个堆中最小的,然后将其余的N-k个数字与堆顶的数字比较,如果大于,则替换成堆顶,然后再重建堆,完成后,这个堆的k个数字就是最大的!!    --要诀是,每次堆顶的数字为这N个数字中第k小的,只要找到最终的堆顶,即找到了最大的k个数字!!

这个算法的复杂度是 logk*N , 重建堆的时间复杂度是log k, 循环N次!!!

如果用最大堆可不可以?

回答是yes。  建立最大堆, 前序遍历打印k个数字即可!

​欢迎感兴趣的码农关注我,目前研究方向为:搜索,智能问答等方向



.