客户端面试

  • 100级台阶,每次上一步或两步,有多少种走法。

573147844013817084101
21

  • 如果200级,你估计有多少种走法(不用编程)。

453973694165307953197296969697410619233826
42

不用编程,估算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.math.BigInteger;
public class Main {

public static void main(String[] args) {
int n = 200;
BigInteger a = BigInteger.ONE;
BigInteger b = BigInteger.ONE;
BigInteger res = BigInteger.ZERO;
for (int i = 2; i <= n; i++) {
res = a.add(b);
a = b;
b = res;
}
System.out.println(res);
System.out.println(res.toString().length());

}
}
  • 给出一个数组,找出两个数[a,b]和为n,不存在则返回[-1,-1]。写出两种解法,不能暴力穷举。

  • 讲讲面向过程、面向对象、面向切面。

  • 指针和数组的关系和区别。

  • 讲讲Android handler。

  • 队列和栈的区别和用途。

  • 两个栈实现队列。

  • 输入Url到浏览器显示过程。

  • http请求方法。

  • get和post区别。

  • surficeView和view的区别。

  • app从点击图标开始的启动全过程。

  • 什么是线程安全。

  • 线程安全有哪些机制。

  • 如何保证 int加加(加号打不出来)线程安全。

  • Android线程间通信有哪些机制。

  • cpu调度方式有哪些。

  • 空间局部性和时间局部性。

  • 数据库乐观锁和悲观锁。

  • 数据库索引作用,优缺点。

  • TCP拥塞控制。

  • https加密传输过程。

  • java内存模型。

  • java垃圾回收算法有哪些。

  • 讲讲标记清除算法。

  • java四中引用。

Java知识点

Java相关

请问JDK和JRE的区别是什么?

JDK :Java 开发工具包,jdk 是整个 Java 开发的核心,它集成了 jre 和一些好用的小工具。
JRE :Java 运行时环境。它主要包含两个部分,jvm 的标准实现和 Java 的一些基本类库。

springboot的注解有什么,原理?

@Bean
用来代替 XML 配置文件里面的 <bean …> 配置。
@ImportResource
如果有些通过类的注册方式配置不了的,可以通过这个注解引入额外的 XML 配置文件,有些老的配置文件无法通过 @Configuration 方式配置的非常管用。
@Import
用来引入额外的一个或者多个 @Configuration 修饰的配置文件类。
@SpringBootConfiguration
这个注解就是 @Configuration 注解的变体,只是用来修饰是 Spring Boot 配置而已,或者可利于 Spring Boot 后续的扩展,源码如下。
@SpringBootApplication:包含了@ComponentScan、@Configuration和@EnableAutoConfiguration注解。其中@ComponentScan让spring Boot扫描到Configuration类并把它加入到程序上下文。
@Configuration 等同于spring的XML配置文件;使用Java代码可以检查类型安全。
@EnableAutoConfiguration 自动配置。
@ComponentScan 组件扫描,可自动发现和装配一些Bean。
@Component可配合CommandLineRunner使用,在程序启动后执行一些基础任务。
@RestController注解是@Controller和@ResponseBody的合集,表示这是个控制器bean,并且是将函数的返回值直 接填入HTTP响应体中,是REST风格的控制器。
@Autowired自动导入。
@PathVariable获取参数。
@JsonBackReference解决嵌套外链问题。
@RepositoryRestResourcepublic配合spring-boot-starter-data-rest使用。

@RequestMapping:@RequestMapping(“/path”)表示该控制器处理所有“/path”的UR L请求。RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。
用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。该注解有六个属性:
params:指定request中必须包含某些参数值是,才让该方法处理。
headers:指定request中必须包含某些指定的header值,才能让该方法处理请求。
value:指定请求的实际地址,指定的地址可以是URI Template 模式
method:指定请求的method类型, GET、POST、PUT、DELETE等
consumes:指定处理请求的提交内容类型(Content-Type),如application/json,text/html;
produces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回

@RequestParam:用在方法的参数前面。
@RequestParam
String a =request.getParameter(“a”)。

@PathVariable:路径变量。如

1
2
3
4
@RequestMapping(“user/get/mac/{macAddress}”) 
public String getByMacAddress(@PathVariable String macAddress){
//do something;
}

Spring Boot的自动配置看起来神奇,其实原理非常简单,背后全依赖于@Conditional注解来实现的。

object类中的hashCode()方法是做什么的,以及其中的hash()方法是做什么的, 为什么有hash()方法还有hashCode()

哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率。在Java的Object类中有一个方法:

1
public native int hashCode();

根据这个方法的声明可知,该方法返回一个int类型的数值,并且是本地方法,因此在Object类中并没有给出具体的实现。

hashCode方法的作用

对于包含容器类型的程序设计语言来说,基本上都会涉及到hashCode。在Java中也一样,hashCode方法的主要作用是为了配合基于散列的集合一起正常运行,这样的散列集合包括HashSet、HashMap以及HashTable。

  为什么这么说呢?考虑一种情况,当向集合中插入对象时,如何判别在集合中是否已经存在该对象了?(注意:集合中不允许重复的元素存在)

  也许大多数人都会想到调用equals方法来逐个进行比较,这个方法确实可行。但是如果集合中已经存在一万条数据或者更多的数据,如果采用equals方法去逐一比较,效率必然是一个问题。此时hashCode方法的作用就体现出来了,当集合要添加新的对象时,先调用这个对象的hashCode方法,得到对应的hashcode值,实际上在HashMap的具体实现中会用一个table保存已经存进去的对象的hashcode值,如果table中没有该hashcode值,它就可以直接存进去,不用再进行任何比较了;如果存在该hashcode值, 就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址,所以这里存在一个冲突解决的问题,这样一来实际调用equals方法的次数就大大降低了,说通俗一点:Java中的hashCode方法就是根据一定的规则将与对象相关的信息(比如对象的存储地址,对象的字段等)映射成一个数值,这个数值称作为散列值。

hash 算法

1
2
3
4
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

首先,假设有一种情况,对象 A 的 hashCode 为 1000010001110001000001111000000,对象 B 的 hashCode 为 0111011100111000101000010100000。

如果数组长度是16,也就是 15 与运算这两个数, 你会发现结果都是0。这样的散列结果太让人失望了。很明显不是一个好的散列算法。

但是如果我们将 hashCode 值右移 16 位,也就是取 int 类型的一半,刚好将该二进制数对半切开。并且使用位异或运算(如果两个数对应的位置相反,则结果为1,反之为0),这样的话,就能避免我们上面的情况的发生。

总的来说,使用位移 16 位和 异或 就是防止这种极端情况。但是,该方法在一些极端情况下还是有问题,比如:10000000000000000000000000 和 1000000000100000000000000 这两个数,如果数组长度是16,那么即使右移16位,在异或,hash 值还是会重复。但是为了性能,对这种极端情况,JDK 的作者选择了性能。毕竟这是少数情况,为了这种情况去增加 hash 时间,性价比不高。

hashmap的put过程 主要就是根据自己看过的源码说一下流程

put 方法
通过 hash 计算下标并检查 hash 是否冲突,也就是对应的下标是否已存在元素。

1
2
3
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
  1. 判断数组是否为空,如果是空,则创建默认长度位 16 的数组。
  2. 通过与运算计算对应 hash 值的下标,如果对应下标的位置没有元素,则直接创建一个。
  3. 如果有元素,说明 hash 冲突了,则再次进行 3 种判断。
    1. 判断两个冲突的key是否相等,equals 方法的价值在这里体现了。如果相等,则将已经存在的值赋给变量e。最后更新e的value,也就是替换操作。
    2. 如果key不相等,则判断是否是红黑树类型,如果是红黑树,则交给红黑树追加此元素。
    3. 如果key既不相等,也不是红黑树,则是链表,那么就遍历链表中的每一个key和给定的key是否相等。如果,链表的长度大于等于8了,则将链表改为红黑树,这是Java8 的一个新的优化。
  4. 最后,如果这三个判断返回的 e 不为null,则说明key重复,则更新key对应的value的值。
  5. 对维护着迭代器的modCount 变量加一。
  6. 最后判断,如果当前数组的长度已经大于阀值了。则重新hash。

ArrayList LinkList的特点

ArrayList是实现了基于动态数组的结构,LinkedList则是基于实现链表的数据结构。

数据的更新和查找
ArrayList的所有数据是在同一个地址上,而LinkedList的每个数据都拥有自己的地址.所以在对数据进行查找的时候,由于LinkedList的每个数据地址不一样,get数据的时候ArrayList的速度会优于LinkedList,而更新数据的时候,虽然都是通过循环循环到指定节点修改数据,但LinkedList的查询速度已经是慢的,而且对于LinkedList而言,更新数据时不像ArrayList只需要找到对应下标更新就好,LinkedList需要修改指针,速率不言而喻

数据的增加和删除
对于数据的增加元素,ArrayList是通过移动该元素之后的元素位置,其后元素位置全部+1,所以耗时较长,而LinkedList只需要将该元素前的后续指针指向该元素并将该元素的后续指针指向之后的元素即可。与增加相同,删除元素时ArrayList需要将被删除元素之后的元素位置-1,而LinkedList只需要将之后的元素前置指针指向前一元素,前一元素的指针指向后一元素即可。当然,事实上,若是单一元素的增删,尤其是在List末端增删一个元素,二者效率不相上下。

红黑树定义

红黑树本质上是一种二叉查找树,但它在二叉查找树的基础上额外添加了一个标记(颜色),同时具有一定的规则。这些规则使红黑树保证了一种平衡,插入、删除、查找的最坏时间复杂度都为 O(logn)。

它的统计性能要好于平衡二叉树(AVL树),因此,红黑树在很多地方都有应用。比如在 Java 集合框架中,很多部分(HashMap, TreeMap, TreeSet 等)都有红黑树的应用,这些集合均提供了很好的性能。

由于 TreeMap 就是由红黑树实现的。

黑色高度
从根节点到叶节点的路径上黑色节点的个数,叫做树的黑色高度。

  1. 每个节点要么是红色,要么是黑色;
  2. 根节点永远是黑色的;
  3. 所有的叶节点都是是黑色的(注意这里说叶子节点其实是上图中的 NIL 节点);
  4. 每个红色节点的两个子节点一定都是黑色;
  5. 从任一节点到其子树中每个叶子节点的路径都包含相同数量的黑色节点;

Java 反射机制

Java 反射机制在程序运行时,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。这种 动态的获取信息 以及 动态调用对象的方法 的功能称为 java 的反射机制。

1
2
3
4
5
6
public class FatherClass {
public String mFatherName;
public int mFatherAge;

public void printFatherMsg(){}
}

多线程相关

synchronized

synchronized 是 Java 中的关键字,是利用锁的机制来实现同步的。

锁机制有如下两种特性:

  • 互斥性:即在同一时间只允许一个线程持有某个对象锁,通过这种特性来实现多线程中的协调机制,这样在同一时间只有一个线程对需同步的代码块(复合操作)进行访问。互斥性我们也往往称为操作的原子性。

  • 可见性:必须确保在锁被释放之前,对共享变量所做的修改,对于随后获得该锁的另一个线程是可见的(即在获得锁时应获得最新共享变量的值),否则另一个线程可能是在本地缓存的某个副本上继续操作从而引起不一致。

synchronized 可以修饰方法和代码块

  • synchronized(this|object) {}
  • synchronized(类.class) {}
  • 修饰非静态方法
  • 修饰静态方法

reentrantLock 除了可重入还有什么关键特性

  • 可重入

现在有方法 m1 和 m2,两个方法均使用了同一把锁对方法进行同步控制,同时方法 m1 会调用 m2。线程 t 进入方法 m1 成功获得了锁,此时线程 t 要在没有释放锁的情况下,调用 m2 方法。由于 m1 和 m2 使用的是同一把可重入锁,所以线程 t 可以进入方法 m2,并再次获得锁,而不会被阻塞住。

  • 公平和非公平锁

公平与非公平指的是线程获取锁的方式。公平模式下,线程在同步队列中通过 FIFO 的方式获取锁,每个线程最终都能获取锁。在非公平模式下,线程会通过“插队”的方式去抢占锁,抢不到的则进入同步队列进行排队。默认情况下,ReentrantLock 使用的是非公平模式获取锁,而不是公平模式。不过我们也可通过 ReentrantLock 构造方法ReentrantLock(boolean fair)调整加锁的模式。

ThreadLocal 会造成什么问题? 为什么会造成内存泄漏?

  • ThreadLocal类用来提供线程内部的局部变量。这些变量在多线程环境下访问(通过get或set方法访问)时能保证各个线程里的变量相对独立于其他线程内的变量,ThreadLocal实例通常来说都是private static类型。 总结:ThreadLocal不是为了解决多线程访问共享变量,而是为每个线程创建一个单独的变量副本,提供了保持对象的方法和避免参数传递的复杂性。
  • ThreadLocal的主要应用场景为按线程多实例(每个线程对应一个实例)的对象的访问,并且这个对象很多地方都要用到。例如:同一个网站登录用户,每个用户服务器会为其开一个线程,每个线程中创建一个ThreadLocal,里面存用户基本信息等,在很多页面跳转时,会显示用户信息或者得到用户的一些信息等频繁操作,这样多线程之间并没有联系而且当前线程也可以及时获取想要的数据。

ThreadLocal类提供了四个对外开放的接口方法

(1) void set(Object value)设置当前线程的线程局部变量的值。
(2) public Object get()该方法返回当前线程所对应的线程局部变量。
(3) public void remove()将当前线程局部变量的值删除,目的是为了减少内存的占用。
(4) protected Object initialValue()返回该线程局部变量的初始值。

在threadLocal设为null和线程结束这段时间不会被回收的,就发生了我们认为的内存泄露。其实这是一个对概念理解的不一致,也没什么好争论的。

最要命的是线程对象不被回收的情况,这就发生了真正意义上的内存泄露。比如使用线程池的时候,线程结束是不会销毁的,会再次使用的就可能出现内存泄露。(在web应用中,每次http请求都是一个线程,tomcat容器配置使用线程池时会出现内存泄漏问题)

  1. 使用ThreadLocal,建议用static修饰 static ThreadLocal headerLocal = new ThreadLocal();
  2. 使用完ThreadLocal后,执行remove操作,避免出现内存溢出情况。

单例模式 synchronized实现懒汉模式?为什么用内部类是线程安全的?

内部类

单例模式,有“懒汉式”和“饿汉式”两种。
懒汉式
单例类的实例在第一次被引用时候才被初始化。
饿汉式
单例类的实例在加载的时候就被初始化。

静态内部类模式

1
2
3
4
5
6
7
8
9
10
public class Singleton { 
private Singleton(){
}
public static Singleton getSingleton(){
return Inner.instance;
}
private static class Inner {
private static final Singleton instance = new Singleton();
}
}
  1. 实现代码简洁。和双重检查单例对比,静态内部类单例实现代码真的是太简洁,又清晰明了。
  2. 延迟初始化。调用getSingleton才初始化Singleton对象。
  3. 线程安全。JVM在执行类的初始化阶段,会获得一个可以同步多个线程对同一个类的初始化的锁。

线程A和线程B同时试图获得Singleton对象的初始化锁,假设线程A获取到了,那么线程B一直等待初始化锁。线程A执行类初始化,就算双重检查模式中伪代码发生了重排序,也不会影响线程A的初始化结果。初始化完后,释放锁。线程B获得初始化锁,发现Singleton对象已经初始化完毕,释放锁,不进行初始化,获得Singleton对象。

数据库相关

添加索引的时候要注意什么

索引可以提高数据的访问速度,但同时也增加了插入、更新和删除操作的处理时间。所以是否要为表增加索引、索引建立在那些字段上,是创建索引前必须要考虑的问题。解决此问题就是分析应用程序的业务处理、数据使用,为经常被用作查询条件、或者被要求排序的字段建立索引。

1、表的主键、外键必须有索引;
2、数据量超过300的表应该有索引;
3、经常与其他表进行连接的表,在连接字段上应该建立索引;
4、经常出现在Where子句中的字段,特别是大表的字段,应该建立索引;
5、索引应该建在选择性高的字段上;
6、索引应该建在小字段上,对于大的文本字段甚至超长字段,不要建索引;
7、复合索引的建立需要进行仔细分析;

聚簇索引:
通常由主键或者非空唯一索引实现的,叶子节点存储了一整行数据
非聚簇索引:
又称二级索引,就是我们常用的普通索引,叶子节点存了索引值和主键值,在根据主键从聚簇索引查

索引优化以及在使用索引的时候要注意什么

1.索引列不要使用函数和运算

  1. 尽量避免使用 != 或 not in或 <> 等否定操作符
  2. 当查询条件为多个的时候,可以采用复合索引
  3. 范围查询对多列查询的影响
  4. 遵循最左匹配原则
    复合索引遵守“最左前缀”原则,即在查询条件中使用了复合索引的第一个字段,索引才会被使用。因此,在复合索引中索引列的顺序至关重要。如果不是按照索引的最左列开始查找,则无法使用索引。
  5. 索引列不会包含NULL值
  6. 尽量避免使用 or 来连接条件
  7. 隐式转换的影响
  8. like 语句的索引失效问题

redis的键的淘汰策略,会达成了redis缓存的淘汰策略

Redis作为一个高性能的内存NoSQL数据库,其容量受到最大内存限制的限制。
事实上,实例中的内存除了保存原始的键值对所需的开销外,还有一些运行时产生的额外内存,包括:

  1. 垃圾数据和过期Key所占空间
  2. 字典渐进式Rehash导致未及时删除的空间
  3. Redis管理数据,包括底层数据结构开销,客户端信息,读写缓冲区等
  4. 主从复制,bgsave时的额外开销

为了防止一次性清理大量过期Key导致Redis服务受影响,Redis只在空闲时清理过期Key。

  • 访问Key时,会判断Key是否过期,逐出过期Key;
  • CPU空闲时在定期serverCron任务中,逐出部分过期Key;
  • 每次事件循环执行的时候,逐出部分过期Key;

网络相关

tcp四次握手,最后的状态是什么?

等待2MSL的时间?(MSL最长报文段寿命Maximum Segment Lifetime,MSL=2)

为什么要等着2MSL,等待多了会造成什么

  1. 保证A发送的最后一个ACK报文段能够到达B。
  2. 防止“已失效的连接请求报文段”出现在本连接中。A在发送完最后一个ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现这种旧的连接请求报文段。

http请求的报文结构,keep-alive是用来做什么的

当使用Keep-Alive模式(又称持久连接、连接重用)时,Keep-Alive功能使客户端到服 务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive功能避免了建立或者重新建立连接。

1
2
Keep-Alive: timeout=5, max=100
timeout:过期时间5秒(对应httpd.conf里的参数是:KeepAliveTimeout),max是最多一百次请求,强制断掉连接

spring spingboot

spring为什么要注入接口,而不是实现类

首先说明,注入的对象确实为实现类的对象。(并不是实现类的代理对象,注入并不涉及代理)

  如果只是单纯注入是可以用实现类接收注入对象的,但是往往开发中会对实现类做增强,如事务,日志等,实现增强的AOP技术是通过动态代理实现的,而spring默认是JDK动态代理,对实现类对象做增强得到的增强类与实现类是兄弟关系,所以不能用实现类接收增强类对象,只能用接口接收。

回答没听过这个概念,然后被引导回到IOC和AOP,以及AOP是什么,实现过程

Java动态代理为我们提供了非常灵活的代理机制,但Java动态代理是基于接口的,如果目标对象没有实现接口我们该如何代理呢?这时候我们就需要使用CGLIB来实现AOP了。

假如我们要使用动态代理实现AOP,那么我们只能在写一个增强的接口,然后让目标类实现增强接口,然后我们就可以使用动态代理实现目标类的增强,可是假如我们不想让目标类实现其他的接口,那么我们就只能使用CGLIB技术来实现目标类的增强了。
CGLIB实现目标类增强的原理是这样的:CGLIB会动态创建一个目标类的子类,然后返回该子类的对象,也就是增强对象,至于增强的逻辑则是在子类中完成的。我们知道子类要么和父类有一样的功能,要么就比父类功能强大,所以CGLIB是通过创建目标类的子类对象来实现增强的,所以:

1
目标子类 = 目标类 + 增强逻辑

口述算法思路

给一个栈的数据结构,实现另外一个数据结构,要求保留栈的特性,同时能够提供去最大值和最小值的方法,时间复杂度为O(1)

最小值思路:用一个辅助栈stack2记住每次入栈stack1的当前最小值:在stack1入栈时,往stack2中加入当前最小值;stack1元素出栈时,stack2也出栈一个元素。最小值从stack2中获取及栈顶元素。O(1)

最大值思路:同上O(1)

image.png

网络编程

哪几种IO类型

  • 阻塞I/O(blocking IO)
  • 非阻塞I/O (nonblocking I/O)
  • I/O 复用 (I/O multiplexing)
  • 信号驱动I/O (signal driven I/O (SIGIO))
  • 异步I/O (asynchronous I/O)

JVM

JVM的内存结构

  • 堆(Heap):线程共享。所有的对象实例以及数组都要在堆上分配。回收器主要管理的对象。
  • 方法区(Method Area):线程共享。存储类信息、常量、静态变量、即时编译器编译后的代码。
  • 方法栈(JVM Stack):线程私有。存储局部变量表、操作栈、动态链接、方法出口,对象指针。
  • 本地方法栈(Native Method Stack):线程私有。为虚拟机使用到的Native 方法服务。如Java使用c或者c++编写的接口服务时,代码在此区运行。
  • 程序计数器(Program Counter Register):线程私有。有些文章也翻译成PC寄存器(PC Register),同一个东西。它可以看作是当前线程所执行的字节码的行号指示器。指向下一条要执行的指令。

image.png

类加载机制

Java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的加载机制。*
Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息:如构造函数,属性和方法等,Java允许用户借由这个Class相关的元信息对象间接调用Class对象的功能,这里就是我们经常能见到的Class类。

image.png

双亲委派模型

双亲委派的意思是如果一个类加载器需要加载类,那么首先它会把这个类请求委派给父类加载器去完成,每一层都是如此。一直递归到顶层,当父加载器无法完成这个请求时,子类才会尝试去加载。这里的双亲其实就指的是父类,没有mother。父类也不是我们平日所说的那种继承关系,只是调用逻辑是这样。

双亲委派模型不是一种强制性约束,也就是你不这么做也不会报错怎样的,它是一种JAVA设计者推荐使用类加载器的方式。

有什么想问我的

有的

  1. 你怎样形容小米公司的企业文化?
  2. 什么类型的员工能在小米公司有比较好的发展?
  3. 关于软件开发工程师-Java方向岗位的技术栈、日常主要工作是什么、期间可以获得晋升机会?
  4. 能给我多讲讲招聘程序吗?
  5. 我没有其他问题了,与您交流非常愉快,能留一张您的名片么?(或者方便加一下您的微信么?)

面试笔记

牛客许愿的小米一面,贡献面经

1
许愿能挺进二面,加油,向着目标冲呀~~~~

——java集合相关

object类中的hashCode()方法是做什么的,以及其中的hash()方法是做什么的, 为什么有hash()方法还有hashCode()

hashmap的put过程 主要就是根据自己看过的源码说一下流程
ArrayList LinkList的特点

——多线程相关

synchronized

reettrantLock 除了可重入还有什么关键特性

threadLocal threadLocal 会造成什么问题 为什么会造成内存泄漏

单例模式 synchronized实现懒汉模式 答 内部类 为什么用内部类是线程安全的?

——数据库相关

添加索引的时候要注意什么

索引优化以及在使用索引的时候要注意什么

redis的键的淘汰策略,会达成了redis缓存的淘汰策略

——网络相关

tcp四次握手,最后的状态是什么,回答等待2MSL

为什么要等着2MSL,等待多了会造成什么

http请求的报文结构,keep-alive是用来做什么的

——spring spingboot

spring中对象增强如何实现 回答没听过这个概念,然后被引导回到IOC和AOP,以及AOP是什么,实现过程

——口述算法思路

给一个栈的数据结构,实现另外一个数据结构,要求保留栈的特性,同时能够提供去最大值和最小值的方法,时间复杂度为O(1)

之前一直没明白是要做什么,后来想到做过类似的题。幸好只是说思路,没有要手写,那个时候已经被前面几个回答的不太好的问题难的很紧张,说做个简单的算法题的时候,我的心紧紧一颤,心想,你确定会简单,还好,还好,结果下来没那么难

——网络编程

哪几种IO类型

还有一个问题 有点忘了,这一块在简历上写了,不过掌握的不是很好

——JVM

类加载机制——回答了一下双亲委派模型相关的内容

——有什么想问我的

面试官蛮年轻,真的很好,一直在引导我回答问题,不会的也没有揪着不放很喜欢说,我们接下来问一个简单的问题,哈哈哈,简单简单着就变得不简单了

是自己比较满意的一次面试

既展示了自己所掌握的知识,也暴露了掌握知识中的问题,给自己后面的复习有了一定的指引

感谢CYC大佬的秘籍

1
2
3
4

最后,重要的话再来几次

许愿能挺进二面,加油,向着目标冲呀~~~~

许愿能挺进二面,加油,向着目标冲呀

1
许愿能挺进二面,加油,向着目标冲呀

440. 字典序的第K小数字

440. 字典序的第K小数字

题目

给定整数 n 和 k,找到 1 到 n 中字典序第 k 小的数字。

注意:1 ≤ k ≤ n ≤ 109。

示例 :

1
2
3
4
5
6
7
8
输入:
n: 13 k: 2

输出:
10

解释:
字典序的排列是 [1, 10, 11, 12, 13, 2, 3, 4, 5, 6, 7, 8, 9],所以第二小的数字是 10。

题解

乍一看这一题貌似毫无头绪,什么是字典序?如何定位这个数?没错,刚接触这个题目的时候,我的脑筋里也是一团乱麻。

但是我觉得作为一个拥有聪明才智的程序员来说,最重要的能力就是迅速抽象问题、拆解问题的能力。经过一段时间的思考,我的脑筋里还是没有答案。

哈哈。

言归正传,我们来分析一下这个问题。

首先,什么是字典序?

什么是字典序?
简而言之,就是根据数字的前缀进行排序,

比如10 < 9,因为10的前缀是1,比9小,

再比如112 < 12,因为112的前缀11小于12。

这样排序下来,会跟平常的升序排序会有非常大的不同。先给你一个直观的感受,一个数乘10,或者加1,哪个大?可能你会吃惊,后者会更大。

但其实掌握它的本质之后,你一点都不会吃惊。

问题建模
画一个图你就懂了。

image.png

每一个节点都拥有10个孩子节点,因为作为一个前缀 ,它后面可以接0~9这十个数字。而且你可以非常容易地发现,整个字典序排列也就是对十叉树进行层序遍历。1, 10, 11, 12, 13 … 100, 101, …

回到题目的意思,我们需要找到排在第k位的数。找到他的排位,需要搞清楚三件事情:

怎么确定一个前缀下所有子节点的个数?
如果第k个数在当前的前缀下,怎么继续往下面的子节点找?
如果第k个数不在当前的前缀,即当前的前缀比较小,如何扩大前缀,增大寻找的范围?
接下来 ,我们一一拆解这些问题。

理顺思路

  1. 确定指定前缀下所有子节点数
    现在的任务就是给定一个前缀,返回下面子节点总数。

我们现在的思路就是用下一个前缀的起点减去当前前缀的起点,那么就是当前前缀下的所有子节点数总和啦。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//prefix是前缀,n是上界
var getCount = (prefix, n) => {
let cur = prefix;
let next = prefix + 1;//下一个前缀
let count = 0;
//当前的前缀当然不能大于上界
while(cur <= n) {
count += next - cur;//下一个前缀的起点减去当前前缀的起点
cur *= 10;
next *= 10;
// 如果说刚刚prefix是1,next是2,那么现在分别变成10和20
// 1为前缀的子节点增加10个,十叉树增加一层, 变成了两层

// 如果说现在prefix是10,next是20,那么现在分别变成100和200,
// 1为前缀的子节点增加100个,十叉树又增加了一层,变成了三层
}
return count;//把当前前缀下的子节点和返回去。
}

当然,不知道大家发现一个问题没有,当next的值大于上界的时候,那以这个前缀为根节点的十叉树就不是满十叉树了啊,应该到上界那里,后面都不再有子节点。因此,count += next - cur还是有些问题的,我们来修正这个问题:

1
count += Math.max(n+1, next) - cur;

你可能会问:咦?怎么是n+1,而不是n呢?不是说好了n是上界吗?

我举个例子,假若现在上界n为12,算出以1为前缀的子节点数,首先1本身是一个节点,接下来要算下面10,11,12,一共有4个子节点。

那么如果用Math.max(n, next) - cur会怎么样?

这时候算出来会少一个,12 - 10加上根节点,最后只有3个。因此我们务必要写n+1。

现在,我们搞定了前缀的子节点数问题。

  1. 第k个数在当前前缀下
    现在无非就是往子树里面去看。

prefix这样处理就可以了。

1
prefix *= 10

3.第k个数不在当前前缀下
说白了,当前的前缀小了嘛,我们扩大前缀。

1
prefix ++;

框架搭建
整合一下刚刚的思路。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let findKthNumber = function(n, k) {
let p = 1;//作为一个指针,指向当前所在位置,当p==k时,也就是到了排位第k的数
let prefix = 1;//前缀
while(p < k) {
let count = getNumber(prefix, n);//获得当前前缀下所有子节点的和
if(p + count > k) { //第k个数在当前前缀下
prefix *= 10;
p++; //把指针指向了第一个子节点的位置,比如11乘10后变成110,指针从11指向了110
} else if(p + count <= k) { //第k个数不在当前前缀下
prefix ++;
p += count;//注意这里的操作,把指针指向了下一前缀的起点
}
}
return prefix;
};

完整代码展示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* @param {number} n
* @param {number} k
* @return {number}
*/
var findKthNumber = function(n, k) {
let getCount = (prefix, n) => {
let count = 0;
for(let cur = prefix, next = prefix + 1; cur <= n; cur *= 10, next *= 10)
count += Math.min(next, n+1) - cur;
return count;
}
let p = 1;
let prefix = 1;
while(p < k) {
let count = getCount(prefix, n);
if(p + count > k) {
prefix *= 10;
p++;
} else if(p + count <= k) {
prefix ++;
p += count;
}
}
return prefix;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class Solution {
/**
* @param n: a integer
* @param k: a integer
* @return: return a integer
*/
public int findKthNumber(int n, int k) {
int curr = 1;
k = k - 1;
while (k > 0) {
int steps = calSteps(n, curr, curr + 1);
if (steps <= k) { //如果不在当前层,减去steps
curr += 1;
k -= steps;
}
else { //说明在当前层,curr*10缩小搜索范围继续查找
curr *= 10;
k -= 1;
}
}
return curr;
}
//use long in case of overflow
public int calSteps(int n, long n1, long n2) { //计算curr开头和curr+1开头之间的字符串数量
int steps = 0;
while (n1 <= n) {
steps += Math.min(n + 1, n2) - n1; //每次加上当前的字符串数量
n1 *= 10; //每次均扩大10倍
n2 *= 10;
}
return steps;
}
}

Java12的新特性

Java12的新特性

Java5的新特性
Java6的新特性
Java7的新特性
Java8的新特性
Java9的新特性
Java10的新特性
Java11的新特性
Java12的新特性
Java13的新特性

image.png

版本号

1
2
3
4
java -version
openjdk version "12" 2019-03-19
OpenJDK Runtime Environment (build 12+33)
OpenJDK 64-Bit Server VM (build 12+33, mixed mode)

从version信息可以看出是build 12+33

特性列表

Shenandoah GC是一个面向low-pause-time的垃圾收集器,它最初由Red Hat实现,支持aarch64及amd64 architecture;ZGC也是面向low-pause-time的垃圾收集器,不过ZGC是基于colored pointers来实现,而Shenandoah GC是基于brooks pointers来实现;如果要使用Shenandoah GC需要编译时–with-jvm-features选项带有shenandoahgc,然后启动时使用-XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC

在jdk源码里头新增了一套基础的microbenchmarks suite

对switch进行了增强,除了使用statement还可以使用expression,比如原来的写法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
System.out.println(6);
break;
case TUESDAY:
System.out.println(7);
break;
case THURSDAY:
case SATURDAY:
System.out.println(8);
break;
case WEDNESDAY:
System.out.println(9);
break;
}

现在可以改为如下写法:

1
2
3
4
5
6
switch (day) {
case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
case TUESDAY -> System.out.println(7);
case THURSDAY, SATURDAY -> System.out.println(8);
case WEDNESDAY -> System.out.println(9);
}

以及在表达式返回值

1
2
3
4
5
6
int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
};

对于需要返回值的switch expression要么正常返回值要么抛出异常,以下这两种写法都是错误的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int i = switch (day) {
case MONDAY -> {
System.out.println("Monday");
// ERROR! Block doesn't contain a break with value
}
default -> 1;
};
i = switch (day) {
case MONDAY, TUESDAY, WEDNESDAY:
break 0;
default:
System.out.println("Second half of the week");
// ERROR! Group doesn't contain a break with value
};

新增了JVM Constants API,具体来说就是java.base模块新增了java.lang.constant包,引入了ConstantDesc接口(ClassDesc、MethodTypeDesc、MethodHandleDesc这几个接口直接继承了ConstantDesc接口)以及Constable接口;ConstantDesc接口定义了resolveConstantDesc方法,Constable接口定义了describeConstable方法;String、Integer、Long、Float、Double均实现了这两个接口,而EnumDesc实现了ConstantDesc接口

64-bit Arm platform (arm64),也可以称之为aarch64;之前JDK有两个关于aarch64的实现,分别是src/hotspot/cpu/arm以及open/src/hotspot/cpu/aarch64,它们的实现重复了,为了集中精力更好地实现aarch64,该特性在源码中删除了open/src/hotspot/cpu/arm中关于64-bit的实现,保留其中32-bit的实现,于是open/src/hotspot/cpu/aarch64部分就成了64-bit ARM architecture的默认实现

java10的新特性JEP 310: Application Class-Data Sharing扩展了JDK5引入的Class-Data Sharing,支持application的Class-Data Sharing;Class-Data Sharing可以用于多个JVM共享class,提升启动速度,最早只支持system classes及serial GC,JDK9对其进行扩展以支持application classes及其他GC算法,并在JDK10中开源出来(以前是commercial feature);JDK11将-Xshare:off改为默认-Xshare:auto,以更加方便使用CDS特性;JDK12的这个特性即在64-bit平台上编译jdk的时候就默认在${JAVA_HOME}/lib/server目录下生成一份名为classes.jsa的默认archive文件(大概有18M)方便大家使用

G1在garbage collection的时候,一旦确定了collection set(CSet)开始垃圾收集这个过程是without stopping的,当collection set过大的时候,此时的STW时间会过长超出目标pause time,这种情况在mixed collections时候比较明显。这个特性启动了一个机制,当选择了一个比较大的collection set,允许将其分为mandatory及optional两部分(当完成mandatory的部分,如果还有剩余时间则会去处理optional部分)来将mixed collections从without stopping变为abortable,以更好满足指定pause time的目标

G1目前只有在full GC或者concurrent cycle的时候才会归还内存,由于这两个场景都是G1极力避免的,因此在大多数场景下可能不会及时会还committed Java heap memory给操作系统。JDK12的这个特性新增了两个参数分别是G1PeriodicGCInterval及G1PeriodicGCSystemLoadThreshold,设置为0的话,表示禁用。当上一次garbage collection pause过去G1PeriodicGCInterval(milliseconds)时间之后,如果getloadavg()(one-minute)低于G1PeriodicGCSystemLoadThreshold指定的阈值,则触发full GC或者concurrent GC(如果开启G1PeriodicGCInvokesConcurrent),GC之后Java heap size会被重写调整,然后多余的内存将会归还给操作系统

细项解读

上面列出的是大方面的特性,除此之外还有一些api的更新及废弃,主要见JDK 12 Release Notes,这里举几个例子。
添加项

  • 支持unicode 11
  • 支持Compact Number Formatting

使用实例如下

1
2
3
4
5
6
7
8
9
10
@Test
public void testCompactNumberFormat(){
var cnf = NumberFormat.getCompactNumberInstance(Locale.CHINA, NumberFormat.Style.SHORT);
System.out.println(cnf.format(1_0000));
System.out.println(cnf.format(1_9200));
System.out.println(cnf.format(1_000_000));
System.out.println(cnf.format(1L << 30));
System.out.println(cnf.format(1L << 40));
System.out.println(cnf.format(1L << 50));
}

输出

1
2
3
4
5
6
1万
2万
100万
11亿
1兆
1126兆
  • String支持transform、indent操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Test
public void testStringTransform(){
System.out.println("hello".transform(new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return s.hashCode();
}
}));
}

@Test
public void testStringIndent(){
System.out.println("hello".indent(3));
}

Files新增mismatch方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Test
public void testFilesMismatch() throws IOException {
FileWriter fileWriter = new FileWriter("/tmp/a.txt");
fileWriter.write("a");
fileWriter.write("b");
fileWriter.write("c");
fileWriter.close();

FileWriter fileWriterB = new FileWriter("/tmp/b.txt");
fileWriterB.write("a");
fileWriterB.write("1");
fileWriterB.write("c");
fileWriterB.close();

System.out.println(Files.mismatch(Path.of("/tmp/a.txt"),Path.of("/tmp/b.txt")));
}
  • Collectors新增teeing方法用于聚合两个downstream的结果
1
2
3
4
5
6
7
8
9
10
11
@Test
public void testCollectorTeeing(){
var result = Stream.of("Devoxx","Voxxed Days","Code One","Basel One")
.collect(Collectors.teeing(Collectors.filtering(n -> n.contains("xx"),Collectors.toList()),
Collectors.filtering(n -> n.endsWith("One"),Collectors.toList()),
(List<String> list1, List<String> list2) -> List.of(list1,list2)
));

System.out.println(result.get(0));
System.out.println(result.get(1));
}
  • CompletionStage新增exceptionallyAsync、exceptionallyCompose、exceptionallyComposeAsync方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Test
public void testExceptionallyAsync() throws ExecutionException, InterruptedException {
LOGGER.info("begin");
int result = CompletableFuture.supplyAsync(() -> {
LOGGER.info("calculate");
int i = 1/0;
return 100;
}).exceptionallyAsync((t) -> {
LOGGER.info("error error:{}",t.getMessage());
return 0;
}).get();

LOGGER.info("result:{}",result);
}
  • JDK12之前CompletionStage只有一个exceptionally,该方法体在主线程执行,JDK12新增了exceptionallyAsync、exceptionallyComposeAsync方法允许方法体在异步线程执行,同时新增了exceptionallyCompose方法支持在exceptionally的时候构建新的CompletionStage

  • Allocation of Old Generation of Java Heap on Alternate Memory Devices

G1及Parallel GC引入experimental特性,允许将old generation分配在诸如NV-DIMM memory的alternative memory device

  • ZGC: Concurrent Class Unloading

ZGC在JDK11的时候还不支持class unloading,JDK12对ZGC支持了Concurrent Class Unloading,默认是开启,使用-XX:-ClassUnloading可以禁用

  • 新增-XX:+ExtensiveErrorReports

-XX:+ExtensiveErrorReports可以用于在jvm crash的时候收集更多的报告信息到hs_err.log文件中,product builds中默认是关闭的,要开启的话,需要自己添加-XX:+ExtensiveErrorReports参数

  • 新增安全相关的改进

支持java.security.manager系统属性,当设置为disallow的时候,则不使用SecurityManager以提升性能,如果此时调用System.setSecurityManager则会抛出UnsupportedOperationException
keytool新增-groupname选项允许在生成key pair的时候指定一个named group
新增PKCS12 KeyStore配置属性用于自定义PKCS12 keystores的生成
Java Flight Recorder新增了security-related的event
支持ChaCha20 and Poly1305 TLS Cipher Suites

  • jdeps Reports Transitive Dependences

jdeps的–print-module-deps, –list-deps, 以及–list-reduce-deps选项得到增强,新增–no-recursive用于non-transitive的依赖分析,–ignore-missing-deps用于suppress missing dependence errors

移除项

  • 移除com.sun.awt.SecurityWarnin
  • 移除FileInputStream、FileOutputStream、Java.util.ZipFile/Inflator/Deflator的finalize方法
  • 移除GTE CyberTrust Global Root
  • 移除javac的-source, -target对6及1.6的支持,同时移除–release选项

废弃项

  • 废弃的API列表见deprecated-list
  • 废弃-XX:+/-MonitorInUseLists选项
  • 废弃Default Keytool的-keyalg值

已知问题

  • Swing不支持GTK+ 3.20及以后的版本
  • 在使用JVMCI Compiler(比如Graal)的时候,JVMTI的can_pop_frame及can_force_early_return的capabilities是被禁用的

其他事项

  • 如果用户没有指定user.timezone且从操作系统获取的为空,那么user.timezone属性的初始值为空变为null
  • java.net.URLPermission的行为发生轻微变化,以前它会忽略url中的query及fragment部分,这次改动新增query及fragment部分,即scheme : // authority [ / path ]变动为scheme : // authority [ / path ] [ ignored-query-or-fragment ]
  • javax.net.ssl.SSLContext API及Java Security Standard Algorithm Names规范移除了必须实现TLSv1及TLSv1.1的规定

小结

  • java12不是LTS(Long-Term Support)版本(oracle版本才有LTS),oracle对该版本的support周期为6个月。这个版本主要有几个更新点,一个是语法层更新,一个是API层面的更新,另外主要是GC方面的更新。
  • 语法层面引入了preview版本的Switch Expressions;API层面引入了JVM Constants API,引入CompactNumberFormat,让NumberFormat支持COMPACTSTYLE,对String、Files、Collectors、CompletionStage等新增方法;GC方面引入了experimental版本的Shenandoah GC,不过oracle build的openjdk没有enable Shenandoah GC support;另外主要对ZGC及G1 GC进行了改进
  • 其中JDK12对ZGC支持了Concurrent Class Unloading,默认是开启,使用-XX:-ClassUnloading可以禁用;对于G1 GC则新增支持Abortable Mixed Collections以及Promptly Return Unused Committed Memory特性

作者:go4it
链接:https://juejin.im/post/5c91fcc9e51d45563b62382c
来源:掘金

2019年度机器学习49个顶级工程汇总

2019年度机器学习49个顶级工程汇总

过去一年中,我们比较了近22000个机器学习开源工程,并筛选了49个顶级项目(筛选率0.22%)。

其中包括以下6个分类

  • 计算机视觉(1~5)
  • 强化学习(6~13)
  • NLP(14~20)
  • GAN(21~26)
  • Neural Network(27~35)
  • Toolkit(36~49)

我们花了很大的精力筛选这个list,并小心的选择出2018年1月到12月间最好的工程。为了保证名单质量,Mybridge AI协同考虑了流行度、参与度、发布时间等多重因素。

计算机视觉
1、Detectron:facebook发布的目标检测工具【18913 star on Github】
项目地址:
https://github.com/facebookresearch/Detectron?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

image.png

2、Openpost:多人实时特征点检测工具【11052 stars on GitHub】
项目地址:
https://github.com/CMU-Perceptual-Computing-Lab/openpose?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

image.png

3、DensePost:2维人体图片转3维的实时映射方法。【4165 stars on Github】
项目地址:
https://github.com/facebookresearch/Densepose?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

image.png

4、Maskrcnn-benchmark:(Pytorch)语义分割与目标检测工具包。【3888 stars on Github】
项目地址:
https://github.com/facebookresearch/maskrcnn-benchmark?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

image.png

5、SNIPER:多尺度目标检测算法。【1963 stars on Github】
项目地址:
https://github.com/mahyarnajibi/SNIPER?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

image.png

强化学习
6、Psychlab:Psychlab实验范例。【5595 stars on Github】
项目地址:
https://github.com/deepmind/lab/tree/master/game_scripts/levels/contributed/psychlab?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

image.png

7、ELF:一个灵活、轻量、可扩展的游戏研究平台。【2406 stars on Github】
项目地址:
https://github.com/pytorch/elf?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

8、TRFL:(TensorFlow)强化学习agent工具包。【2312 stars on Github】
项目地址:
https://github.com/deepmind/trfl?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

9、Horizon:首个用于大规模需求的开源强化学习平台。【1703 stars on Github】
项目地址:
https://github.com/facebookresearch/Horizon?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

10、Chess-alpha-zero:国际象棋强化学习项目(基于AlphaGo Zero方法)。【1307 stars on Github】
项目地址:
https://github.com/Zeta36/chess-alpha-zero?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

11、Dm_control:DeepMind工具包。【1231 stars on Github】
项目地址:
https://github.com/deepmind/dm_control?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

12、MAMEToolkit:基于强化学习的电子游戏python库。【437 stars on Github】
项目地址:
https://github.com/M-J-Murray/MAMEToolkit?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

13、Reaver:模块化的深度强化学习框架(星际争霸2)。【355 stars on Github】
项目地址:
https://github.com/inoryy/reaver?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

NLP
14、Bert:BERT的TensorFlow代码,以及预训练模型。【11703 stars on Github】
项目地址:
https://github.com/google-research/bert?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

15、Pytext:基于Pytorch的神经语言模型框架。【4466 stars on Github】
项目地址:
https://github.com/facebookresearch/pytext?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

16、Bert-as-service:BERT模型的网络服务版本
项目地址:
https://github.com/hanxiao/bert-as-service?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

17、UnsupervisedMT:基于Phrase的无监督机器翻译方法。【1068 stars on Github】
项目地址:
https://github.com/facebookresearch/UnsupervisedMT?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

18、DecaNLP:NLP十项全能工具,多任务模型。【1648 stars on Github】
项目地址:
https://github.com/salesforce/decaNLP?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

19、NLP-architect:来自英特尔AI实验室的python工具包,包含了当前NLP领域的多种最佳模型。【1751 stars on Github】
项目地址:
https://github.com/NervanaSystems/nlp-architect?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

20、Gluon-nlp:NLP工具包。【1263 stars on Github】
项目地址:
https://github.com/dmlc/gluon-nlp?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

GAN
21、DeOldify:一个基于深度学习的图像补全工具包。【5060 stars on Github】
项目地址:
https://github.com/jantic/DeOldify?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

22、Progressive_growing_of_gans:GAN的变种实现,提高生产质量、稳定性以及多样性。
项目地址:
https://github.com/tkarras/progressive_growing_of_gans?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

23、MUNIT:多模态无监督图像翻译。【1339 stars on Github】
项目地址:
https://github.com/NVlabs/MUNIT?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

24、Transparent_latent_gan:使用监督学习来解释GAN的隐空间信息。【1337 stars on Github】
项目地址:
https://github.com/SummitKwan/transparent_latent_gan?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

25、Gandissect:基于Pytorch的可视化以及理解GAN的神经元信息。【1065 stars on Github】
项目地址:
https://github.com/CSAILVision/gandissect?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

26、GANimation:单张图片的表情变换。【869 stars on Github】
项目地址:
https://github.com/albertpumarola/GANimation?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more
神经网络
27、Fastai:加速神经网络训练过程,并提高准确率。【11597 stars on Github】
项目地址:
https://github.com/fastai/fastai?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

28、DeepCreamPy:图像修复。【7046 stars on Github】
项目地址:
https://github.com/deeppomf/DeepCreamPy?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

29、Augmentor v0.2、图像增强工具包。【2805 stars on Github】
项目地址:
https://github.com/mdbloice/Augmentor?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

30、Graph_nets:Tensorflow的图网络构建工具。【2723 stars on Github】
项目地址:
https://github.com/deepmind/graph_nets?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

31、Textgenrnn:使用预训练字符级RNN生成文本。【1900 stars on Github】
项目地址:
https://github.com/minimaxir/textgenrnn?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

32、Person-blocker:图像中自动删除人像。【1806 stars on Github】
项目地址:
https://github.com/minimaxir/person-blocker?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

33、Deepvariant:DNA序列数据的分析工具
项目地址:
https://github.com/google/deepvariant?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

34、Video-nolocal-net:non-local神经网络的视频分类方法。【1049 stars on Github】
项目地址:
https://github.com/facebookresearch/video-nonlocal-net?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

35、Ann-visualizer:神经网络可视化工具。【922 stars on Github】
项目地址:
https://github.com/Prodicode/ann-visualizer?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

工具包
36、Tfjs:一个基于JS的ML模型训练部署工具包。【10268 stars on Github】
项目地址:
https://github.com/tensorflow/tfjs?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

37:Dopamine:快速的强化学习研究框架。【7142 stars on Github】
项目地址:
https://github.com/google/dopamine?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

38、Lime:分类器解释工具包。【5173 stars on Github】
项目地址:
https://github.com/marcotcr/lime?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

39、Autokeras:自动机器学习的开源软件库。【4520 stars on Github】
项目地址:
https://github.com/jhfjhfj1/autokeras?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

40、Shap:神经网络解释工具。【3496 stars on Github】
项目地址:
https://github.com/slundberg/shap?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

41、MMdnn:模型适配器。【3021 stars on Github】
项目地址:
https://github.com/Microsoft/MMdnn?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

42、Mlflow:机器学习生命周期管理。【3013 stars on Github】
项目地址:
https://github.com/mlflow/mlflow?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

43、Mace:面向移动计算平台的深度学习推断框架。【2979 stars on Github】
项目地址:
https://github.com/XiaoMi/mace?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

44、PySyft:关注安全性的深度学习库。【2595 stars on Github】
项目地址:
https://github.com/OpenMined/PySyft?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

45、Adanet:AutoML计算库。【2293 stars on Github】
项目地址:
https://github.com/tensorflow/adanet?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

46、Tencent-ml-images:最大的多标签图像数据库。【2094 stars on Github】
项目地址:
https://github.com/Tencent/tencent-ml-images?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

47、Donkeycar、开源的软硬件自动驾驶平台。【1207 stars on Github】

项目地址:
https://github.com/autorope/donkeycar?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

48、PocketFlow:自动模型压缩框架。【1677 stars on Github】
项目地址:
https://github.com/Tencent/PocketFlow?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

49、DALI:深度学习应用的优化工具包以及数据处理扩展引擎。【1013 stars on Github】
项目地址:
https://github.com/NVIDIA/dali?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more

传送门

OpenCV边缘检测

OpenCV边缘检测

image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('1024.jpg',0)
edges = cv2.Canny(img,100,200)

plt.subplot(121),plt.imshow(img,cmap='gray')
plt.title('original'),plt.xticks([]),plt.yticks([])
plt.subplot(122),plt.imshow(edges,cmap='gray')
plt.title('edge'),plt.xticks([]),plt.yticks([])

plt.show()

Java面试题

基础与框架

String类能被继承吗,为什么?

不可以,因为String类有final修饰符,而final修饰的类是不能被继承的,实现细节不允许改变。

1
public final class String implements java.io.Serializable, Comparable<String>, CharSequence

根据程序上下文环境,Java关键字final有“这是无法改变的”或者“终态的”含义,它可以修饰非抽象类、非抽象类成员方法和变量。你可能出于两种理解而需要阻止改变:设计或效率。
  final类不能被继承,没有子类,final类中的方法默认是final的。
  final方法不能被子类的方法覆盖,但可以被继承。
  final成员变量表示常量,只能被赋值一次,赋值后值不再改变。
  final不能用于修饰构造方法。
  注意:父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final类型的。

如果一个类不允许其子类覆盖某个方法,则可以把这个方法声明为final方法。
  使用final方法的原因有二:
  第一、把方法锁定,防止任何继承类修改它的意义和实现。
  第二、高效。编译器在遇到调用final方法时候会转入内嵌机制,大大提高执行效率。(这点有待商榷,《Java编程思想》中对于这点存疑)

下面这段话摘自《Java编程思想》第四版第143页:
“使用final方法的原因有两个。第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率。在早期的Java实现版本中,会将final方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升。在最近的Java版本中,不需要使用final方法进行这些优化了。”

关于String类,要了解常量池的概念

1
String s = new String(“xyz”);  //创建了几个对象

答案: 1个或2个, 如果”xyz”已经存在于常量池中,则只在堆中创建”xyz”对象的一个拷贝,否则还要在常量池中在创建一份

1
String s = "a"+"b"+"c"+"d"; //创建了几个对象

答案: 这个和JVM实现有关, 如果常量池为空,可能是1个也可能是7个等

String,Stringbuffer,StringBuilder的区别?

1、用来处理字符串常用的类有3种:String、StringBuffer和StringBuilder
2、三者之间的区别:
都是final类,都不允许被继承;
String类长度是不可变的,StringBuffer和StringBuilder类长度是可以改变的;
StringBuffer类是线程安全的,StringBuilder不是线程安全的;

String 和 StringBuffer:
1、String类型和StringBuffer类型的主要性能区别:String是不可变的对象,因此每次在对String类进行改变的时候都会生成一个新的string对象,然后将指针指向新的string对象,所以经常要改变字符串长度的话不要使用string,因为每次生成对象都会对系统性能产生影响,特别是当内存中引用的对象多了以后,JVM的GC就会开始工作,性能就会降低;

2、使用StringBuffer类时,每次都会对StringBuffer对象本身进行操作,而不是生成新的对象并改变对象引用,所以多数情况下推荐使用StringBuffer,特别是字符串对象经常要改变的情况;

3、在某些情况下,String对象的字符串拼接其实是被Java Compiler编译成了StringBuffer对象的拼接,所以这些时候String对象的速度并不会比StringBuffer对象慢,例如:

1
2
String s1 = “This is only a” + “ simple” + “ test”;
StringBuffer Sb = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);

生成 String s1对象的速度并不比 StringBuffer慢。其实在Java Compiler里,自动做了如下转换:

1
2
3
4
5
Java Compiler直接把上述第一条语句编译为:
String s2 = “This is only a”;
String s3 = “ simple”;
String s4 = “ test”;
String s1 = s2 + s3 + s4;

传送门

ArrayList和LinkedList有什么区别

ArrayList是实现了基于动态数组的结构,LinkedList则是基于实现链表的数据结构。

数据的更新和查找
ArrayList的所有数据是在同一个地址上,而LinkedList的每个数据都拥有自己的地址.所以在对数据进行查找的时候,由于LinkedList的每个数据地址不一样,get数据的时候ArrayList的速度会优于LinkedList,而更新数据的时候,虽然都是通过循环循环到指定节点修改数据,但LinkedList的查询速度已经是慢的,而且对于LinkedList而言,更新数据时不像ArrayList只需要找到对应下标更新就好,LinkedList需要修改指针,速率不言而喻

数据的增加和删除
对于数据的增加元素,ArrayList是通过移动该元素之后的元素位置,其后元素位置全部+1,所以耗时较长,而LinkedList只需要将该元素前的后续指针指向该元素并将该元素的后续指针指向之后的元素即可。与增加相同,删除元素时ArrayList需要将被删除元素之后的元素位置-1,而LinkedList只需要将之后的元素前置指针指向前一元素,前一元素的指针指向后一元素即可。当然,事实上,若是单一元素的增删,尤其是在List末端增删一个元素,二者效率不相上下。

传送门

类的实例化顺序,比如父类静态数据,构造函数,字段,子类静态数据,构造函数,字段,他们的执行顺序

此题考察的是类加载器实例化时进行的操作步骤(加载–>连接->初始化)。
父类静态变量、
父类静态代码块、
子类静态变量、
子类静态代码块、
父类非静态变量(父类实例成员变量)、
父类构造函数、
子类非静态变量(子类实例成员变量)、
子类构造函数。

传送门

用过哪些Map,都有什么区别,HashMap是线程安全的吗,并发下使用的Map是什么,他们内部原理分别是什么,比如hashcode,扩容等

Hashtable,HashMap,ConcurrentHashMap

线程不安全的HashMap
因为多线程环境下,使用Hashmap进行put操作会引起死循环,导致CPU利用率接近100%,所以在并发情况下不能使用HashMap。

HashMap
HashMap内部实现是一个桶数组,每个桶中存放着一个单链表的头结点。其中每个结点存储的是一个键值对整体(Entry),HashMap采用拉链法解决哈希冲突

传送门

效率低下的HashTable容器
HashTable容器使用synchronized来保证线程安全,但在线程竞争激烈的情况下HashTable的效率非常低下。因为当一个线程访问HashTable的同步方法时,其他线程访问HashTable的同步方法时,可能会进入阻塞或轮询状态。如线程1使用put进行添加元素,线程2不但不能使用put方法添加元素,并且也不能使用get方法来获取元素,所以竞争越激烈效率越低。

ConcurrentHashMap的锁分段技术
HashTable容器在竞争激烈的并发环境下表现出效率低下的原因,是因为所有访问HashTable的线程都必须竞争同一把锁,那假如容器里有多把锁,每一把锁用于锁容器其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效的提高并发访问效率,这就是ConcurrentHashMap所使用的锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。

传送门

hashcode() 方法,在object类中定义如下:

1
public native int hashCode();

native说明是一个本地方法,它的实现是根据本地机器相关的。当然我们可以在自己写的类中覆盖hashcode()方法,比如String、Integer、Double。。。。等等这些类都是覆盖了hashcode()方法的
例如String类中:就是以31为权,每一位为字符的ASCII值进行运算,用自然溢出来等效取模。(为什么取31?主要是因为31是一个奇质数,所以31i=32i-i=(i<<5)-i,这种位移与减法结合的计算相比一般的运算快很多).

1
2
3
4
5
6
7
8
9
10
11
12
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;

for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}

HashMap为什么get和set那么快,concurrentHashMap为什么能提高并发

HashMap 底层是基于 数组 + 链表 组成的

传送门

抽象类和接口的区别,类可以继承多个类么,接口可以继承多个接口么,类可以实现多个接口么

实现 抽象类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现。子类使用关键字implements来实现接口。它需要提供接口中所有声明的方法的实现。
抽象类和接口的区别

由于Java不支持多继承,子类不能够继承多个类,但可以实现多个接口。因此你就可以使用接口来解决它。

接口可以继承多个接口。
java类是单继承的。classB Extends classA
java接口可以多继承。Interface3 Extends Interface0, Interface1, interface……
不允许类多重继承的主要原因是,如果A同时继承B和C,而B和C同时有一个D方法,A如何决定该继承那一个呢?
但接口不存在这样的问题,接口全都是抽象方法继承谁都无所谓,所以接口可以继承多个接口。

什么情况下会发生栈内存溢出

方法递归调用产生这种结果

栈是线程私有的,他的生命周期与线程相同,每个方法在执行的时候都会创建一个栈帧,用来存储局部变量表,操作数栈,动态链接,方法出口灯信息。局部变量表又包含基本数据类型,对象引用类型(局部变量表编译器完成,运行期间不会变化)

所以我们可以理解为栈溢出就是方法执行是创建的栈帧超过了栈的深度。那么最有可能的就是方法递归调用产生这种结果。栈溢出(StackOverflowError)

什么是nio,原理

NIO是为了弥补传统I/O工作模式的不足而研发的,NIO的工具包提出了基于Selector(选择器)、Buffer(缓冲区)、Channel(通道)的新模式;Selector(选择器)、可选择的Channel(通道)和SelectionKey(选择键)配合起来使用,可以实现并发的非阻塞型I/O能力。

NIO的工作原理是什么?

  在并发型服务器程序中使用NIO,实际上是通过网络事件驱动模型实现的。我们应用Select机制,不用为每一个客户端连接新启线程处理,而是将其注册到特定的Selector对象上,这就可以在单线程中利用Selector对象管理大量并发的网络连接,更好的利用了系统资源;采用非阻塞I/O的通信方式,不要求阻塞等待I/O操作完成即可返回,从而减少了管理I/O连接导致的系统开销,大幅度提高了系统性能。

  当有读或写等注册事件发生时,可以从Selector中获得相应的SelectionKey,从SelectionKey中可以找到发生的事件和该事件所发生的具体的SelectableChannel,以获得客户端发送过来的数据。由于在非阻塞网络I/O中采用了事件触发机制,处理程序可以得到系统的主动通知,从而可以实现底层网络I/O无阻塞、流畅地读写,而不像在原来的阻塞模式下处理程序需要不断循环等待。使用NIO,可以编写出性能更好、更易扩展的并发型服务器程序。

  并发型服务器程序的实现代码:应用NIO工具包,基于非阻塞网络I/O设计的并发型服务器程序与以往基于阻塞I/O的实现程序有很大不同,在使用非阻塞网络I/O的情况下,程序读取数据和写入数据的时机不是由程序员控制的,而是Selector决定的。

  使用非阻塞型I/O进行并发型服务器程序设计分三个部分:1. 向Selector对象注册感兴趣的事件;2.从Selector中获取所感兴趣的事件;3. 根据不同的事件进行相应的处理。

  在进行并发型服务器程序设计时,通过合理地使用NIO工具包,就可以达到一个或者几个Socket线程就可以处理N多个Socket的连接,大大降低我们对服务器程序的预算压力。同时我们利用它更好地提高系统的性能,使我们的工作得到更加有效地开展。

传送门

反射中,Class.forName和ClassLoader区别

Java中Class.forName和classloader都可以用来对类进行加载。

  • Class.forName(“className”);

    其实这种方法调运的是:Class.forName(className, true, ClassLoader.getCallerClassLoader())方法
    参数一:className,需要加载的类的名称。
    参数二:true,是否对class进行初始化(需要initialize)
    参数三:classLoader,对应的类加载器
  • ClassLoader.laodClass(“className”);

    其实这种方法调运的是:ClassLoader.loadClass(name, false)方法
    参数一:name,需要加载的类的名称
    参数二:false,这个类加载以后是否需要去连接(不需要linking)

可见Class.forName除了将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块。

而classloader只干一件事情,就是将.class文件加载到jvm中,不会执行static中的内容,只有在newInstance才会去执行static块。

传送门

tomcat结构,类加载器流程

Tomcat 的总体结构

image.png

从上图中可以看出 Tomcat 的心脏是两个组件:Connector 和 Container,关于这两个组件将在后面详细介绍。Connector 组件是可以被替换,这样可以提供给服务器设计者更多的选择,因为这个组件是如此重要,不仅跟服务器的设计的本身,而且和不同的应用场景也十分相关,所以一个 Container 可以选择对应多个 Connector。多个 Connector 和一个 Container 就形成了一个 Service,Service 的概念大家都很熟悉了,有了 Service 就可以对外提供服务了,但是 Service 还要一个生存的环境,必须要有人能够给她生命、掌握其生死大权,那就非 Server 莫属了。所以整个 Tomcat 的生命周期由 Server 控制。

什么是类加载器?
虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类。实现这个动作的代码模块称为“类加载器”。

传送门

讲讲Spring事务的传播属性,AOP原理,动态代理与cglib实现的区别,AOP有哪几种实现方式

Spring的beanFactory和factoryBean的区别

Spring加载流程

Spring如何管理事务的

多线程

线城池的最大线程数目根据什么确定

多线程的几种实现方式,什么是线程安全,什么是重排序

volatile的原理,作用,能代替锁么

sleep和wait的区别,以及wait的实现原理

Lock与synchronized 的区别,synchronized 的原理,什么是自旋锁,偏向锁,轻量级锁,什么叫可重入锁,什么叫公平锁和非公平锁

用过哪些原子类,他们的参数以及原理是什么

用过哪些线程池,他们的原理简单概括下,构造函数的各个参数的含义,比如coreSize,maxsize等

有一个第三方接口,有很多个线程去调用获取数据,现在规定每秒钟最多有10个线程同时调用它,如何做到。

spring的controller是单例还是多例,怎么保证并发的安全

用三个线程按顺序循环打印abc三个字母,比如abcabcabc

ThreadLocal用过么,原理是什么,用的时候要注意什么

如果让你实现一个并发安全的链表,你会怎么做

JVM相关

jvm中一次完整的GC流程(从ygc到fgc)是怎样的,重点讲讲对象如何晋升到老年代,几种主要的jvm参数等

你知道哪几种垃圾收集器,各自的优缺点,重点讲下cms

当出现了内存溢出,你怎么排错

JVM内存模型的相关知识了解多少

简单说说你了解的类加载器

JAVA的反射机制

网络

http1.0和http1.1有什么区别

TCP三次握手和四次挥手的流程,为什么断开连接要4次,如果握手只有两次,会出现什么

TIME_WAIT和CLOSE_WAIT的区别

说说你知道的几种HTTP响应码

当你用浏览器打开一个链接的时候,计算机做了哪些工作步骤

Linux下IO模型有几种,各自的含义是什么

TCP/IP如何保证可靠性,数据包有哪些数据组成

架构设计与分布式:

tomcat如何调优,各种参数的意义

常见的缓存策略有哪些,你们项目中用到了什么缓存系统,如何设计的,Redis的使用要注意什么,持久化方式,内存设置,集群,淘汰策略等

如何防止缓存雪崩12.用java自己实现一个LRU

分布式集群下如何做到唯一序列号

设计一个秒杀系统,30分钟没付款就自动关闭交易

如何做一个分布式锁

用过哪些MQ,怎么用的,和其他mq比较有什么优缺点,MQ的连接是线程安全的吗

MQ系统的数据如何保证不丢失

分布式事务的原理,如何使用分布式事务

什么是一致性hash

什么是restful,讲讲你理解的restful

如何设计建立和保持100w的长连接?

解释什么是MESI协议(缓存一致性)

说说你知道的几种HASH算法,简单的也可以

什么是paxos算法

redis和memcached 的内存管理的区别

一个在线文档系统,文档可以被编辑,如何防止多人同时对同一份文档进行编辑更新

算法

10亿个数字里里面找最小的10个

有1亿个数字,其中有2个是重复的,快速找到它,时间和空间要最优

2亿个随机生成的无序整数,找出中间大小的值

遍历二叉树

数据库

数据库隔离级别有哪些,各自的含义是什么,MYsql默认的隔离级别是是什么,各个存储引擎优缺点

高并发下,如何做到安全的修改同一行数据,乐观锁和悲观锁是什么,INNODB的行级锁有哪2种,解释其含义

SQL优化的一般步骤是什么,怎么看执行计划,如何理解其中各个字段的含义,索引的原理?

数据库会死锁吗,举一个死锁的例子,mysql怎么解决死锁

MYsql的索引实现方式

聚集索引和非聚集索引的区别

数据库中 BTREE和B+tree区别

TensorFlow 2.0 RC is available

image.png

TensorFlow 2.0 RC

工具
探索可支持和加速 TensorFlow 工作流程的工具。

image.png

CoLab

Colaboratory 是一个免费的 Jupyter 笔记本环境,不需要进行任何设置就可以使用,并且完全在云端运行。借助 Colaboratory,您只需点击一下鼠标,即可在浏览器中执行 TensorFlow 代码。

TensorBoard

一套可视化工具,用于理解、调试和优化TensorFlow程序。

What-If工具

一种无代码的方式探究机器学习模型的工具,对模型的理解、调试和公平性很有用。可在TensorFlow和Jupyter或CoLab笔记本中使用。

ML Perf

全面的机器学习基准测试套件,用于衡量机器学习软件框架、机器学习硬件加速器和机器学习云端平台的性能。

XLA

XLA(加速线性代数)是一种特定领域的线性代数编译器,能够优化TensorFlow计算,它可以提高服务器和移动平台的运行速度改进内存使用情况和可移植性。

TensorFlow Playground

在浏览器中设计神经网络。别担心,不会使浏览器崩溃。

TensorFlow Research Cloud

加入TensorFlow Research Cloud(TFRC)计划后,研究人员可于申请访问Cloud TPU来加快实现下一波研究突破;我们免费提供1000个Cloud TPU.

nohup:在linux后台运行程序

image.png

nohup:在linux后台运行程序

今天在工作中,lz要在Linux系统上运行一个java程序,这个程序要在系统中持续运行。随后lz无意将ssh窗口关掉了,发现java程序停止了。原来,当使用ssh连接到系统运行程序的时候,该程序已经和你的ssh连接绑定了。如果你关闭连接,该程序就会停止。还有一个情景:如果要在后台运行多个java程序的时候,就需要启动多个ssh窗口,这样很麻烦。有没有方法来解决这个问题呢?答案是肯定的。

1.使用nohup来执行命令,它会把命令自动调到linux后台运行,不锁定当前ssh窗口,也不会被ctrl + c,alt + F4之类打断程序的动行。

1
nohup java -jar test.jar &

执行完该命令后,终端会显示如下信息:

1
2
[1] 27945
nohup: 忽略输入并把输出追加到"nohup.out"

[1]:该后台任务的jobid
27945:是该进程的pid
nohup.out:是该任务的输出位置

2.要指定重定向的文件,如下:

1
nohup java -jar test.jar > test.log 2>&1 &

3.如果一个任务已经在前台执行,那就使用以下方法来将任务调整到后台:

(1)首先,在正在执行任务的终端使用ctrl+z

1
[1]+  已停止               java -jar test.jar

(2)使用bg命令将该任务调整至后台(fg与之相反,将后台任务调整至前台)

1
bg %1(1是jobid)

如果不知道jobid,也可以使用jobs命令来查询。

但是任务的输出还是会打印到终端上的(具体怎么将输出重定向到别的地方,lz也不造)。而且,这时该任务还是与当前终端相关联的,关闭终端还是会断掉该任务的。使用下面命令来解决:

1
disown -h %1

这样再也不用担心关掉终端会停止掉任务喽!!!

PS:再来说说nohup吧。nohup的意思是no hang up,就是说关掉终端是不会挂掉程序的。如果开始执行命令时只使用&:

1
java -jar test.jar &

那么该任务也会在后台执行,但是一旦关掉终端该任务还是会挂掉,所以这就是nohup的用处了。

原文链接

骨传导

骨传导

image.png

骨传导是一种声音传导方式,即通过将声音转化为不同频率的机械振动,通过人的颅骨、骨迷路、内耳淋巴液传递、螺旋器、听神经、听觉中枢来传递声波。相对于通过振膜产生声波的经典声音传导方式,骨传导省去了许多声波传递的步骤,能在嘈杂的环境中实现清晰的声音还原,而且声波也不会因为在空气中扩散而影响到他人。

骨传导技术分为骨传导扬声器技术和骨传导麦克风技术:

  1. 骨传导扬声器技术 用于受话,受话即听取声音。气导扬声器是把电信号转化为的声波(振动信号传至听神经。而骨传导扬声器则是电信号转化的声波(振动信号)直接通过骨头传至听神经。声波(振动信号)的传递介质不同。
  2. 骨传导麦克风技术 用于送话,送话即收集声音。气导送话是声波通过空气传至麦克风,而骨传导送话则直接通过骨头传递。

利用这些骨传导技术制造的耳机,称之为骨传导耳机,也被称作骨导耳机、骨感耳机、骨传耳机和骨传感耳机。

原文链接

三阶魔方解法

三阶魔方解法

预备篇:三阶魔方相关知识
在本教程中,统一使用官方配色(上黄、下白、左橙、右红、前蓝、后绿),并在还原的过程中,白色作为底色。

下图中,A、B、C分别表示顶层、中层、底层;D为中心块,在还原的过程中以此作为参照色(即该面所最终还原的颜色);E为棱块,每块有两个颜色;F为角块,每块有三个颜色。

在本教程中,分别用Front、Back、Left、Right、Up、Down的首字母表示前面、后面、左面、右面、上面、下面的顺时针90度旋转,带撇号的为逆时针90度逆转,带数字2的为180度旋转。

image.png

image.png

第一步:完成底层四棱
子步骤一:拼成黄心白瓣小花
如下图①所示,我们只要在黄色中心块的四周的棱块都挨着白色即可。

对于在中层的白色棱,如②所示,只需转一个90度即可将白色朝上;对于在顶层、底层朝外的白色棱,如③所示,先在白色所在面转动90度后变成②的情况再处理;而在底层朝下的白色棱,如④所示,则通过180度旋转即可将白色朝上。

值得留意的是⑤之类的情况,如果直接转90度将中层白色块朝上,那么会破坏掉上方原先已有的白色块。此时要先转动顶层(此例为U’),将空位转到对应位置,方可使该白色块转上去。

image.png

子步骤二:找到相应颜色并掉落花瓣
先随意选定一个白色棱(下图以白红棱为例),转动顶层(或扭转中底层),直到该棱侧面的颜色与中心块吻合时,以该中心块为轴转动180度,使其落到白色中心旁边。用同样的方法处理其他三个棱之后,在底层会形成白色的十字,棱的侧面也与中心块相连。

image.png

第二步:完成底层四角
这一步我们不仅要让白色的四角全都聚集在下面,还要留意其角块侧面的颜色也要吻合。

如下图的上半部分所示,我们先在顶层寻找含白色的角块,同时观察该角块另外两种颜色,转动顶层(或扭转中底层),使之处在相应颜色的两个中心块之间。

当角块转到相应位置后,观察白色的朝向,做相应的公式:

①为白色朝右,做U’ F’ U F;
②为白色朝前,做U R U’ R’;
③为白色朝上,做三遍的公式①。
当顶层无任何白色角块时,此时再观察底层有无错误朝向或位置的白色角块:

④在底层,白色朝右,做两遍的公式①;
⑤在底层,白色朝前,做两遍的公式②;
⑥在底层,错误位置角块,先做公式①将其赶回顶层,然后找到相应正确位置还原。
用同样的方法处理其他三个角之后,底面为全白色,侧面会形成倒T字。

image.png

第三步:完成中层四棱
如下图的上半部分所示,我们先在顶层寻找不含黄色的棱块,同时观察该棱块另外两种颜色,转动顶层(或扭转中底层),使之朝外的颜色与中心块相吻合。

当棱块转到相应位置后,观察最终所归的空位,并将空位置于右前方,做相应的公式(前面的公式①与②,在这里称为甲与乙):

①情况做U’ F’ U F U R U’ R’(先甲后乙);
②情况做U R U’ R’ U’ F’ U F(先乙后甲);
当顶层全为有黄色的棱块时,此时再观察中层有无错误朝向或位置的棱块:

③与④情况,先做甲+乙将其赶回顶层,然后找到相应正确位置还原。
用同样的方法处理其他三个棱之后,第二层即完成。

image.png

第四步:完成顶面十字
现在观察顶面的棱与中心块所构成的图形(忽视角块黄色是否朝上与否)分为“点、线、拐、十字”四种情况。找到相应的情况并按图示朝向摆放后,按照下流程图每次做R’ U’ F’ U F R(R’+甲+R)直到变成十字为止。其中“线”的情况还有一条捷径,即F R U R’ U’ F’。

image.pngCube solve 7a.png

第五步:调整顶棱顺序
先转动顶层(或扭转中底层),直到至少有两个棱侧面的颜色与中心块吻合。

现在观察另外两个错误的棱处于相邻还是相对位置,如果没有,则此步跳过;如果是相邻的,则将两个错误的置一前一右,做丙公式U’ F’ U’ F U’ F’ U2 F;如果是相对的,则将两个错误的置一左一后,先做丙公式,然后转下顶层变为相邻的,再置一前一右做丙公式完成。

image.pngCube solve 8.png

第六步:调整顶角顺序
观察顶角,找到在正确位置的一个角(朝向是否正确暂时不考虑)。如果四角都在正确位置,则此步跳过;如果只有一个,则将正确的角置于左前方,做丁公式U’ L’ U R U’ L U R’(做一遍仍未成功则再做第二遍);如果没有一个角在正确位置,则先做丁公式然后变成有一个角在正确位置再相应处理。

image.pngCube solve 9.png

第七步:调整顶角朝向
此时我们统一将蓝色中心块保持前面放置,需要注意的是在操作的过程中魔方的底层会被暂时性打乱,不过不要紧,只要正确操作完后魔方会正常还原。

观察顶层前右方的角块的黄色朝向,做戊公式F’ R F R’二或四遍使黄色朝上。完成一个角块的朝向处理之后,要转动顶层(U、U’、U2),并保持蓝色中心块在前面不动,再处理其他角块朝向。(在每一角落都要扭)

image.pngCube solve 10.png

维基百科

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×