Victor's Code Journey
Victor's Code Journey

算法之布尔表达式化简

布尔基础:

  • 逻辑表达式: 由逻辑变量和与 $\land$ ,或 $\lor$ ,非 $\neg$ 3种运算符连接所构成的表达式。

  • 析取式: 表达式之间都通过逻辑或连接的复合表达式。

  • 合取式: 表达式之间都通过逻辑与连接的复合表达式。

  • 合取范式 (Conjunctive Normal Form)2 是命题公式的一个标准型,它由一系列析取子句 用合取操作连接而来。如 $(a) \land (a \lor \neg c) \land (b \lor c)$

  • 与之相反,析取范式 (Disjunctive Normal Form) 是命题公式的另一个标准型,它由一系列 合取子句 用 析取操作 连接而来。如 $(a) \lor (a \land \neg c) \lor (b \land c)$

表达式化简:

  • 表达式相等: 两个表达式具有同样的变量,且对于变量的任意一组取值,表达式的值均相等,这两个表达式是相等的
  • 最小项: 如果某个表达式的某个乘积(与)项包含了表达式的全部变量,其中每个表达式都以原变量或是反变量的形式出现。n个变量可以有2^n个最小项。
  • 主析取式: 可以将表达式化简为全部由最小项组成的唯一表达式,也被称为主析取式(符合析取范式).

线程对性能的影响

随着多核芯片的广泛使用,线程是提升性能的首选方案。适当提升一点线程数会很好;事实上,拥有太多线程可能会使程序陷入困境。过多的线程主要对两个方面有影响:

  • 首先,在太多线程之间划分固定数量的工作会使每个线程分到的工作太少,以至于启动和终止线程的开销会影响有用的工作。
  • 其次,运行太多线程会因为共享有限硬件资源,从而导致产生过多的开销。

Flink源码学习-准备工作

本文是学习flink源码前的准备工作。在开始之前,先做好准备工作:

  • 安装JDK8+,Flink 依赖 Java 8 或更新的版本来进行构建。
    • 自flink1.15 开始需要Java 11(如无必要不使用更高版本的JDk去build)
  • 安装Maven 3 ( Maven 3.3.x 可以构建 Flink,但是不能正确地屏蔽掉指定的依赖。Maven 3.2.5 可以正确地构建库文件)
  • 安装Scala 2.11或2.12
    • 自flink1.15 开始需要Scala 2.12

版本规范

版本格式:主版本号.次版本号.修订号,版本号递增规则如下:

  • 主版本号:当你做了不兼容的 API 修改,
  • 次版本号:当你做了向下兼容的功能性新增,
  • 修订号:当你做了向下兼容的问题修正。

先行版本号及版本编译元数据可以加到主版本号.次版本号.修订号 的后面,作为延伸。

Java File WatchService

java 的 nio包提供了对文件系统的监控服务,主要使用系统原生文件服务,同时在没有原生服务的时候,使用轮询来监控。下面是一个代码示例:

    String path = "/tmp";
    // 获取当前OS平台下的文件系统监控器
    WatchService watcher = FileSystems.getDefault().newWatchService();
    //将监控器注册给指定的文件节点,该方法会让监控器线程就绪并运行,调用完后监控器就开始监控

    /* 文件变化枚举类型
     * ENTRY_CREATE:创建
     * ENTRY_DELETE:删除
     * ENTRY_MODIFY:修改
     */
    Paths.get(path).register(watcher,
        StandardWatchEventKinds.ENTRY_CREATE,
        StandardWatchEventKinds.ENTRY_DELETE,
        StandardWatchEventKinds.ENTRY_MODIFY);

    while (true) {
        WatchKey key = watcher.take();
        // 获得WatchKey(监控池)中的具体监控信息,
        // !!! 一个文件变化动作可能会引发一系列的事件,因此WatchKey中保存着一个事件列表List<WatchEvent<?>> list
        for (WatchEvent<?> event: key.pollEvents()) {

            System.out.println(event.context() + " comes to " + event.kind());
        }
        // 完成一次监控就需要重置监控器一次.
        boolean valid = key.reset(); 
        if (!valid) {
            break;
        }
    }
// ---------- output --------------
// tmp.log comes to ENTRY_DELETE

AOP标准:aopalliance

AOP Alliance 项目是许多对Aop和java有浓厚兴趣的软件开发人员联合成立的开源项目,旨在确定Aop的标准。面向切面编程是设计和开发应用程序的一个好方案,AOP 提供了一种通用方法来构建关注点(横切关注点),并将它们灵活地作为模块插入应用。但是,也带来了问题: 不同的AOP实现并不能适配所有环境。

大多数人不相信完美系统,我们认为一个系统总是能处理给定的一个问题和环境(不需要适配其他)。现在已经有了很多的AOP实现或AOP相关的技术,例如,通用代理,拦截器或字节码翻译工具。具体如下:

  • AspectJ: 面向切面的源码级和字节码级别的织入器。
  • AspectWerkz: 一个面向切面框架(字节码动态织入,支持XML配置)。
  • BCEL: 一个字节码翻译器
  • JAC: 一个面向切面框架(字节码动态织入,可配置切面)
  • Javassist: 字节码翻译器,有高级API。
  • JBoss-AOP: 拦截和基于元数据的AOP框架(支持独立运行和在JBoss应用服务器种运行)
  • JMangler: 一个字节码翻译器,支持兼容翻译
  • Nanning: 一个面向切面织入器框架
  • Prose: 一个面向切面动态字节码织入框架

对我们而言,这些实现没有好与坏的区别,都适合于某些问题或环境。AOP Alliance的目的不是提出新的AOP模型,也不是提供一个更好的AOP实现来解决所有场景的问题。其目的在于提炼所有AOP实现的共同核心能力:

  • 避免重复造轮子,尽量重用
  • 简化某个环境下现有AOP组件的适配
  • 简化开发工具集成AOP能力的工作