Java面试--容易忽略的知识点

容易忽略的知识点

并行计算【详解】

步骤:

1.将数据拆分到每个节点上【如何拆分:要保证每个节点都能独立计算;1.将大的数据根据尺寸进行拆分 2.根据用户首字母进行拆分】

2.每个几点并行的计算出结果【每个节点算出什么样的结果,这时得到中间结果】

3.将结果汇总

例【外部排序】  如何排序10G个元素

使用扩展的归并排序

归并排序:将数据分为左右两半,分别归并排序,再把两个有序数据归并【稳定排序】

排序过程:

如何排序10G个元素

思路:

将数据进行切分,分为很多段,每一段都送到一个节点进行排序,每一段的数据量要控制到可以在内存中放下,每一个节点进行排序即可,这时每一个节点都会是一个有序的序列,如下图所示:

每一个有序的序列同时送给一个归并节点,这个归并节点使用算法进行归并(不断选各个节点最小的数),归并完成 即可完成操作,难点在于如何进行归并;

归并节点实现过程:

1.使用 堆 的数据结构, 堆 :根是最小的元素

2.完成 堆 的构建

3.建立缓冲区 (归并节点内存中只需要放每个数据源中最小的元素即可,但存在问题,如将 1 拿掉之后,再将 2 读进来需要读一次外部存储,这个读取操作会很慢,效率很低,通常做法是建立缓冲区:读取一批数据放在缓冲区,减小读取次数)

归并:使用  Iterable<T> 接口:

1.可以不断获取下一个元素

2.元素存储/获取方式被抽象,与归并节点无关

3.Iterable<T> merge(List<Iterable<T>> sortedData)

归并数据源来自 Iterable<T> .next()

1.如果缓冲区空,读取下一批元素放入缓冲区

2.给出缓冲区第一个元素

3.可配置项:缓冲区大小,如何读取下一批元素

多线程【详解】

典型的两种死锁情形:【详解】
(一)线程自己将自己锁住
一般情况下,如果同一个线程先后两次调用lock,在第二次调⽤用时,由于锁已经被占用,该线程会挂起等待占用锁的线程释放锁,然而锁正是被自己占用着的,该线程又被挂起而没有机会释放锁,因此 就永远处于挂起等待状态了,于是就形成了死锁(Deadlock)。
(二)多线程抢占锁资源被困
又如线程A获 得了锁1,线程B获得了锁2,这时线程A调用lock试图获得锁2,结果是需要挂起等待线程B释放 锁2,而这时线程B也调用lock试图获得锁1,结果是需要挂起等待线程A释放锁1,于是线程A和B都 永远处于挂起状态了,死锁再次形成。 

添加死锁:

死锁分析:1.在任何地方都可以线程切换,甚至在一句语句中间 

2.要尽力设想对自己最 不利 的情况

死锁条件,必须同时满足:

1.互斥等待

2.hold and wait

3.循环等待

4.无法剥夺的等待

死锁防止:  

1.破除互斥等待      ---一般无法破除

2.破除hold and wait       ---一次性获取所有资源

3.破除循环等待          ---按顺序获取资源

4.破除无法剥夺的等待     ---加入超时【不得已的办法】

线程池【详解】

线程的生命周期,线程的生命周期可以利用以下的图解来更好的理解:

第一步,是用new Thread()的方法新建一个线程,在线程创建完成之后,线程就进入了就绪(Runnable)状态,此时创建出来的线程进入抢占CPU资源的状态,当线程抢到了CPU的执行权之后,线程就进入了运行状态(Running),当该线程的任务执行完成之后或者是非常态的调用的stop()方法之后,线程就进入了死亡状态。而我们在图解中可以看出,线程还具有一个则色的过程,这是怎么回事呢?当面对以下几种情况的时候,容易造成线程阻塞,第一种,当线程主动调用了sleep()方法时,线程会进入则阻塞状态,除此之外,当线程中主动调用了阻塞时的IO方法时,这个方法有一个返回参数,当参数返回之前,线程也会进入阻塞状态,还有一种情况,当线程进入正在等待某个通知时,会进入阻塞状态。那么,为什么会有阻塞状态出现呢?我们都知道,CPU的资源是十分宝贵的,所以,当线程正在进行某种不确定时长的任务时,Java就会收回CPU的执行权,从而合理应用CPU的资源。我们根据图可以看出,线程在阻塞过程结束之后,会重新进入就绪状态,重新抢夺CPU资源。这时候,我们可能会产生一个疑问,如何跳出阻塞过程呢?又以上几种可能造成线程阻塞的情况来看,都是存在一个时间限制的,当sleep()方法的睡眠时长过去后,线程就自动跳出了阻塞状态,第二种则是在返回了一个参数之后,在获取到了等待的通知时,就自动跳出了线程的阻塞过程。

在一个应用程序中,我们需要多次使用线程,也就意味着,我们需要多次创建并销毁线程。而创建并销毁线程的过程势必会消耗内存。而在Java中,内存资源是及其宝贵的,所以,我们就提出了线程池的概念,线程池的好处,就是可以方便的管理线程,也可以减少内存的消耗。

定义:预先建立好线程,等待任务派发

线程池内部:

线程池参数:

1.corePoolSize:线程池中初始线程数量,可能处于等待状态

2.maximumPoolSize:线程池中最大允许线程数量

3.keepAliveTime:超出 corePoolSize 部分线程如果等待这些时间将被回收

线程池_Java Excutor Framework演示

1.线程池创建

2.任务派发

3.利用 Future 检查任务结果

代码实现:

ExecutorTester.java

package interview.adv;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import interview.designpattern.task.CodingTask;

public class ExecutorTester {

  public static void main(String[] args)
      throws InterruptedException, ExecutionException {
    ExecutorService executor = Executors.newFixedThreadPool(3); 	//创建线程池

    List<Future<?>> taskResults = new LinkedList<>();
    for (int i = 0; i < 10; i++) {		//创建 10 个任务
      taskResults.add(executor.submit(new CodingTask(i)));
    }
    System.out.println("10 tasks dispatched successfully.");

    for (Future<?> taskResult : taskResults) {
      taskResult.get();
    }

    System.out.println("All tasks finished.");
    executor.shutdown();
  }
}

输出:

  

资源管理

Java 垃圾回收【图解Java 垃圾回收机制】

1.不被引用的对象会被回收

2.垃圾回收包括 Minor GC 和 Full GC

3.垃圾回收时所有运行暂停

Java 资源管理

1.内存会被回收,资源不会被释放

2. databaseConnection 需要 databaseConnection.close() 来释放

Java 1.7

C++ 资源管理

1.没有 finally ,没有 try with resourcce

2.有析构函数

猜你喜欢

转载自blog.csdn.net/jianghao233/article/details/82862152