并发编程
- Executors.newSingleThreadExecutor()
- Executors.newFixedThreadPool(int)
- Executors.newCachedThreadPool()
- 类锁和对象锁
- synchronized 修饰方法、代码块,修饰不同地方分别对应类锁或对象锁
- notify(), notifyAll()
- 公平锁和非公平锁。自旋锁
- 原子性(atomicity),可视性(volatility)
- wait()和sleep()
- Condition:await(),signal(),signalAll()
- CountDownLatch,CyclicBarrier:用来同步一个或多个任务,强制它们等待由其他任务执行的一组操作完成
- Timer定时任务原理基本理解,单线程 + 最小堆 + 不断轮询
- Timer、ScheduledThreadPool、DelayQueue,Quartz
- 由于ScheduledThreadPool的实现是从queue里拿到第一个任务后时间未到则sleep到该任务的时间,假如sleep 10s,这个时候进来一个任务是5s后执行,那是不是非要等sleep 10s后执行了前一个任务再执行新任务呢,很显然不能这么设计。所以在加入queue时会判断:如果queue为空,则唤醒线程,如果加入的任务排第一,则也会唤醒线程。
- 时间轮算法Netty实现:转数。kafka实现:多层时间轮。
- Greenplum数据库、ServiceMesh、Datahub、非侵入打点技术
- 编程范式:
- 面向对象:封装、继承、多态
- 面向过程:只关心解决问题的步骤与过程
- 函数式编程:程序看作函数,输入自变量,输出因变量,函数像变量一样作为参数传递。
- 面向接口编程:属于面向对象体系的一部分,多态与抽象
- JVisualVM ,JDK提供的一个JVM运行监控可视化工具
Effective Java
- 静态工厂方法
- 建造者模式(Builder)
- 私有化构造方法实现单例模式
- 抽象类是可以被实例化的,只不过是间接:Calendar是抽象类,从Calendar.getInstance() 中所获得的实例其实就是一个 “GreogrianCalendar” 对象。
- 枚举类被设计为单例模式,构造方法必须私有。jvm会自动实例化枚举对象(使用到时)
- 避免创建不必要的对象:比如创建正则表达式的Pattern一次可以用于多次匹配。
private static final Pattern PHONE = Pattern.compile("");
static boolean isPhone(String s){
return PHONE.matcher(s).matches();
}
- 优先使用基本类型而不是装箱类型
- 让程序中的错误尽可能提前暴露
- try-with-resources语句代替try-finally:声明了一种或多种资源的try语句(实现了java.lang.AutoCloseable接口的对象,和实现了java.io.Closeable接口的对象,都可以当做资源使用。)
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br =
new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
-
native关键字:说明这个方法是原生函数,也就是这个方法是用C/C++语言实现的,并且被编译成了DLL,由java去调用
-
覆盖方法的返回类型可以是被覆盖方法返回类型的子类,其他不行
-
public static int compareUnsigned(int x, int y) {
return compare(x + MIN_VALUE, y + MIN_VALUE);
} -
当用final作用于类的成员变量时,成员变量必须在定义时或者构造器中进行初始化赋值,而且final变量一旦被初始化赋值之后,就不能再被赋值了。被final修饰的引用变量一旦初始化赋值之后就不能再指向其他的对象
-
嵌套类有4种:1.静态成员类,2.非静态成员类,3.匿名类,4.局部类。除了第一种外,其他三种都称为内部类。静态成员类是最简单的一种嵌套类,最好把它看作是普通的类,只是碰巧被声明在另一个类的内部而已。
-
当非静态成员类被创建的时候,与外围类的一个实例相关联,这种关联无法被修改
-
transient关键字:不需要序列化的属性前添加。
-
总之,使用原生态类型会在运行时导致异常,因此不要在新代码中使用。原生态类型只是为了与引入泛型之前的遗留代码进行兼容和互用而提供的。让我们做个快速的回顾:Set是个参数化类型,表示可以包含任何对象类型的一个集合;Set<?>则是一个通配符烈性,表示只能包含某种未知对象类型的一个集合;Set则是个原生态类型,她脱离了泛型系统。前两种是安全的,最后一种不安全。
-
List 和 List<?> 的区别,类型参数和通配符
-
可变参数和泛型不能良好地合作,因为可变参数设施是构建在*数组之上的一个技术露底,泛型数组有不同的类型规则。
-
stream的groupingBy(p->p.lifeCycle,()->new EnumMap<>(LifeCycle.class), toSet() ),可以指定映射实现
-
枚举的本质是Enum的子类
-
Enum<E extends Enum> 表示泛型参数就是自己,变成代码就是类似于这样的 public class Test extends Enum
-
<T extends Enum < T > >这泛型就表示T是个枚举
-
@Repeatable 可重复的注解
-
stream流中map和flatmap的用法区别。
-
方法引用与lambda表达式
方法引用类型 | 范例 | Lambda等式 |
---|---|---|
静态 | Integer::parseInt | str -> Integer.parseInt(str) |
有限制 | Instant.now()::isAfter | Instant then = Instant.now() ;t -> then.isAfter(t) |
无限制 | String::toLowerCase | str -> str.toLowerCase() |
类构造器 | TreeMap<K,V>::new | () -> new TreeMap<K,V> |
数组构造器 | int[]::new | len -> new int[len] |
Stream.iterate(BigInteger.valueOf(2), BigInteger::nextProbablePrime).limit(20).forEach(System.out::print);
Stream.iterate(BigInteger.valueOf(2), t->t.nextProbablePrime()).limit(20).forEach(System.out::print);
- 将stream流转为Iterable的适配器方法
public static <E> Iterable<E> iterableOf(Stream<E> stream) {
return stream::iterator;
}
有了此方法就可以用for-each语句遍历任何Stream:
for(ProcessHandle p:iterableOf(ProcessHandle.allProcesses())){
}
- 重载方法的选择是静态的(编译时确定),而覆盖方法的选择是动态的(选择的依据是被调用方法所在对象的运行时类型)
- 正确使用optional才能减少判空代码,不然只是换了判空方式而且还造成额外性能开销。(另外,使用它是显示告诉调用者结果可能为空,因为确保不为空就没必要用它包装)
Optional增添了完全不同于空判断的编程体验,即链式管道流的函数式的编程体验。它的引入是为了在链式管道流(Pipeline)的处理中给延后(Laziness)赋值的情形提供一种统一的处理方式。
- 死循环的写法,源码中几乎是for(; ; )
编译器没做优化的前提下:for (;;)相比 while(1) 指令少,不占用寄存器
- for-each 循环不仅能遍历集合和数组,还能遍历实现Iterable 接口的任何对象。
public interface Iterable<E>{
Iterator<E> iterator();
}
DDD领域驱动
- 贫血对象充血对象,领域服务
其他
- 与 2 有关的用位运算优化:快速幂算法、取余、判断奇偶数 、乘以2的m次方或除以2的m次方