容易忽略的知识点
并行计算【详解】
步骤:
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.有析构函数