一、Java Api

1. 文件监听

背景:之前第三方系统使用 FTP 传输一些静态资源到服务器的指定文件夹中,包含图片、视频、txt 文本文件。其中需要读取 txt 的文本内容,并将其整理落库。本来想使用 js 脚本处理的,后来领导说尽量写在一起。于是使用该 API 实现。

WatchService 接口可以用来实现对系统的文件进行监听。

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
34
35
36
37
38
39
40
41
@Test
public void watchFileTest() {
// 监听路径
String path = "D:\\";
try {
// 创建 WatchService 实例
WatchService watchService = FileSystems.getDefault().newWatchService();
// 这里只监听 创建 事件
// 除此之外,还有修改、删除、特殊事件
// StandardWatchEventKinds.ENTRY_MODIFY
// StandardWatchEventKinds.ENTRY_DELETE
// StandardWatchEventKinds.OVERFLOW
Paths.get(path).register(watchService, StandardWatchEventKinds.ENTRY_CREATE);

while (true) {
// 一直等待事件,如果没有就阻塞
// 如果对事件不是那么敏感,可以使用 watchService.poll(long timeout, TimeUnit unit) 每隔多少时间获取一次
WatchKey key = watchService.take();
// 获取事件列表
List<WatchEvent<?>> events = key.pollEvents();
// 由于只监听了一种事件,这里使用流处理。
events.stream()
.filter(e -> Objects.equals(e.kind(), StandardWatchEventKinds.ENTRY_CREATE))
.forEach(e -> {
String fileName = e.context().toString();
System.out.println("创建了 [" + fileName + "] 文件");
try {
// 休眠 1ms 是为了让系统完成相应的回调函数,
// 否则你会看到输出多次 ”创建了 [" + fileName + "] 文件“ 内容
Thread.sleep(100);
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
});
// 重置 watchKey 继续监听文件夹的事件
key.reset();
}
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
}
}

2. ServiceLoader 获取某个接口的所有实现类

Java 6 引入了一个新功能,用于发现和加载与给定接口匹配的实现:Service Provider Interface (SPI)。SPI 的核心是 ServiceLoader 类。它具有延迟发现和加载实现的作用。它使用上下文类路径来查找提供程序实现并将它们放在内部缓存中。可以参见官方文档:https://docs.oracle.com/javase/tutorial/ext/basics/spi.html

1
2
3
4
5
@Test
public void testServiceLoader() {
java.util.ServiceLoader<AssetsStrategy> strategies = java.util.ServiceLoader.load(AssetsStrategy.class);
strategies.forEach(System.out::println);
}

当然,如果直接执行以上代码是没有任何打印内容的。因为它还需要一点儿额外的配置。你需要在 resources/META-INF 目录下新建 services 目录,然后在新建的目录中添加一个文件,这个 文件名 必须是接口的 所在包路径+接口名称全限定名称,不带任何后缀,且区分大小写。最后按照同样的格式把实现了该接口的实现类写到该文件中。

以上面的测试方法举个栗子,AssetsStrategy 是一个接口,该接口位于 com.example.strategy 包,并且它有 Model1Model2 两个实现类。在 resources/META-INF/services/com.example.strategy.AssetsStrategy 文件中(该文件必须采用 UTF-8 编码)添加以下内容:

resources/META-INF/services/com.example.strategy.AssetsStrategy
1
2
com.example.model.Model1
com.example.model.Model2

然后运行上面的测试代码,就可以看到结果啦~

3. JUC

LockSupport

LockSupport 可以实现线程的阻塞和释放,并且该类对外提供的方法都是静态方法:parkxxx 阻塞线程,unparkxxx 唤醒被阻塞的线程。


本站由 江湖浪子 使用 Stellar 1.28.1 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。