您的位置:首页 > 职场人生

程序员麦兜【编程笔记】-看了一点面试题

2019-06-13 16:20 92 查看

面向对象特征

-------封装,继承,多态和抽象

  1. 封装
    封装给对象提供了隐藏内部特性和行为的能力。对象提供一些能被其他对象访问的方法 来改 变它内部的数据。在 Java 当中,有 3 种修饰符: public, private 和 protected。每一 种修饰符 给其他的位于同一个包或者不同包下面对象赋予了不同的访问权限。 下面列出了使用封装的一些好处: 通过隐藏对象的属性来保护对象内部的状态。 提高了代码的可用性和可维护性,因为对象的行为可以被单独的改变或者是扩展。 禁止对象之间的不良交互提高模块化
  2. 继承
    继承给对象提供了从基类获取字段和方法的能力。继承提供了代码的重用行,也可以在 不修改类的情况下给现存的类添加新特性。
  3. 多态
    多态是编程语言给不同的底层数据类型做相同的接口展示的一种能力。一个多态类型上 的操作可以应用到其他类型的值上面。
  4. 抽象
    抽象是把想法从具体的实例中分离出来的步骤,因此,要根据他们的功能而不是实现细 节来创建类。 Java 支持创建只暴漏接口而不包含方法实现的抽象的类。这种抽象技术 的主要目的是把类的行为和实现细节分离开。

Java中堆和栈的区别

栈内存用来存储局部变量和方法调用
-------堆内存用来存储java中的对象。无论是成员变量,局部变量,还是类变量,它们指向的对象都存储在堆内存中
-------栈内存归属于单个线程,每个线程都会有一个栈内存,其存储的变量只能在其所属线程中可见,即栈内存可以理解成线程的私有内存
-------堆内存中的对象对所有线程可见,堆内存中的对象可以被所有线程访问。
-------如果栈内存没有可用空间,JVM会抛出java.lang.StackOverFlowError异常
------如果堆内存没有可用空间,JVM会抛出java.lang.OutOfMemoryError异常
-------栈内存远远小于堆内存
-------栈内存调节-Xss -Xms设置堆开始时的大小 -Xmx设置堆的最大值

反射的用途和实现

-------JAVA的反射机制主要提供了以下功能
1.在运行时构造一个类的对象
2.判断一个类所具有的变量和成员方法
3.调用一个对象的方法
4.生成动态代理
5.反射最大的应用就是框架

sleep()、join()、yield()有什么区别

1.sleep方法
在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度 程序精度和准确性的影响。让其他线程有机会继续执行,但它并不释放对象锁。也就是如 果有Synchronized同步块,其他线程仍然不能访问共享数据。注意该方法要捕获异常。
比如有两个线程同时执行(没有Synchronized),一个线程优先级为MAX_PRIORITY,另一 个为MIN_PRIORITY,如果没有Sleep()方法,只有高优先级的线程执行完成后,低优先级 的线程才能执行;但当高优先级的线程sleep(5000)后,低优先级就有机会执行了。 总之,sleep()可以使低优先级的线程得到执行的机会,当然也可以让同优先级、高优先级的 线程有执行的机会。
2.yield()方法
yield()方法和sleep()方法类似,也不会释放“锁标志”,区别在于,它没有参数,即yield()方 法只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态 后马上又被执行,另外yield()方法只能使同优先级或者高优先级的线程得到执行机会,这也 和sleep()方法不同。
3.join()方法
Thread的非静态方法join()让一个线程B“加入”到另外一个线程A的尾部。在A执行完毕之前, B不能工作。
Thread t = new MyThread();
t.start();
t.join();
保证当前线程停止执行,直到该线程所加入的线程完成为止。然而,如果它加入的线程没有 存活,则当前线程不需要停止。

线程池的几种方式

------newFixedThreadPool(int nThreads)
创建一个固定长度的线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数 量,这时线程规模将不再变化,当线程发生未预期的错误而结束时,线程池会补充一个新的 线程
------newCachedThreadPool()
创建一个可缓存的线程池,如果线程池的规模超过了处理需求,将自动回收空闲线程,而当 需求增加时,则可以自动添加新线程,线程池的规模不存在任何限制
------newSingleThreadExecutor()
这是一个单线程的Executor,它创建单个工作线程来执行任务,如果这个线程异常结束,会 创建一个新的来替代它;它的特点是能确保依照任务在队列中的顺序来串行执行
------newScheduledThreadPool(int corePoolSize)
创建了一个固定长度的线程池,而且以延迟或定时的方式来执行任务,类似于Timer。

线程的生命周期

------新建(new Thread)
当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。 例如:Thread t1=new Thread();
------就绪(runnable)
线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队 等候得到CPU资源。例如:t1.start();
------运行(running)
线程获得CPU资源正在执行任务(run()方法),此时除非此线程自动放弃CPU资源或者有 优先级更高的线程进入,线程将一直运行到结束。
------死亡(dead)
当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态 等待执行。
自然终止:正常运行run()方法后终止
异常终止:调用**stop()**方法让一个线程终止运行
------堵塞(blocked)
由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。 正在睡眠:用sleep(long t) 方法可使线程进入睡眠方式。一个睡眠着的线程在指定的时间过 去可进入就绪状态。
正在等待:调用wait()方法。(调用motify()方法回到就绪状态)
被另一个线程所阻塞:调用suspend()方法。(调用resume()方法恢复)

悲观锁和乐观锁

------悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。再比如Java里面的同步原语synchronized关键字的实现也是悲观锁。
------乐观锁:顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁。在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: