Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 94f61f1

Browse files
test file watcher 2
1 parent 68aaa01 commit 94f61f1

File tree

7 files changed

+426
-7
lines changed

7 files changed

+426
-7
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package nio.file.watch;
2+
3+
import java.nio.file.Path;
4+
import java.nio.file.WatchEvent.Kind;
5+
6+
/**
7+
* @author zacconding
8+
* @Date 2018年10月08日
9+
* @GitHub : https://github.com/zacscoding
10+
*/
11+
public interface FileListener {
12+
13+
String getIdentifier();
14+
15+
boolean isHandle(Kind<?> eventType);
16+
17+
void handleEvent(Kind<?> eventType, Path context);
18+
}

‎javademo/src/main/java/nio/file/watch/FileModifiedListener.java‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@
66
* @GitHub : https://github.com/zacscoding
77
*/
88
public interface FileModifiedListener {
9+
910
void onModified();
1011
}

‎javademo/src/main/java/nio/file/watch/FileWatcher.java‎

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import java.util.Map;
1313
import java.util.concurrent.ConcurrentHashMap;
1414
import java.util.concurrent.TimeUnit;
15+
import org.slf4j.Logger;
16+
import org.slf4j.LoggerFactory;
1517

1618
/**
1719
* @author zacconding
@@ -20,7 +22,9 @@
2022
*/
2123
public class FileWatcher {
2224

25+
private static final Logger logger = LoggerFactory.getLogger(FileWatcher.class);
2326
public static FileWatcher INSTANCE = new FileWatcher();
27+
2428
private static final Object LOCK = new Object();
2529
private ThreadGroup threadGroup;
2630
private Map<String, Long> threadIds;
@@ -31,16 +35,12 @@ public FileWatcher() {
3135

3236
public boolean regist(File file, FileModifiedListener listener) {
3337
if (file == null || file.isDirectory()) {
38+
logger.warn("Failed to regist file. file is null or directory. file : {}", file);
3439
return false;
3540
}
3641

3742
try {
3843
Path path = file.toPath();
39-
if (path.toFile().isDirectory()) {
40-
// have to regist file
41-
return false;
42-
}
43-
4444
Path parentPath = path.getParent();
4545
String parentDir = parentPath.toAbsolutePath().toString();
4646
String fileName = path.getFileName().toString();
@@ -178,8 +178,6 @@ public void run() {
178178
listener.onModified();
179179
}
180180
}
181-
182-
watchKey.reset();
183181
});
184182
}
185183
} catch (InterruptedException e) {
Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
package nio.file.watch;
2+
3+
import java.io.File;
4+
import java.io.IOException;
5+
import java.nio.file.ClosedWatchServiceException;
6+
import java.nio.file.FileSystems;
7+
import java.nio.file.Path;
8+
import java.nio.file.StandardWatchEventKinds;
9+
import java.nio.file.WatchEvent;
10+
import java.nio.file.WatchEvent.Kind;
11+
import java.nio.file.WatchKey;
12+
import java.nio.file.WatchService;
13+
import java.util.Map;
14+
import java.util.concurrent.ConcurrentHashMap;
15+
import java.util.concurrent.TimeUnit;
16+
import org.apache.shiro.util.StringUtils;
17+
import org.slf4j.Logger;
18+
import org.slf4j.LoggerFactory;
19+
20+
/**
21+
* @author zacconding
22+
* @Date 2018年10月08日
23+
* @GitHub : https://github.com/zacscoding
24+
*/
25+
public class FileWatcher2 {
26+
27+
public static final FileWatcher2 INSTANCE = new FileWatcher2();
28+
29+
private static final Logger logger = LoggerFactory.getLogger(FileWatcher2.class);
30+
private static final Object LOCK = new Object();
31+
32+
private ThreadGroup threadGroup;
33+
private Map<String, Long> threadIds;
34+
35+
public FileWatcher2() {
36+
initialize();
37+
}
38+
39+
public boolean regist(File file, FileListener fileListener) {
40+
if (file == null) {
41+
logger.warn("Failed to register detecting file because file is null");
42+
return false;
43+
}
44+
45+
Path path = file.toPath();
46+
Path detectingPath = null;
47+
48+
if (file.isDirectory()) {
49+
detectingPath = path;
50+
} else {
51+
detectingPath = path.getParent();
52+
}
53+
54+
try {
55+
final String absoluteDirPath = detectingPath.toAbsolutePath().toString();
56+
WatcherThread watcherThread = getThread(absoluteDirPath, false);
57+
58+
if (watcherThread == null) {
59+
synchronized (LOCK) {
60+
if ((watcherThread = getThread(absoluteDirPath, false)) == null) {
61+
WatchService watcher = FileSystems.getDefault().newWatchService();
62+
path.register(watcher, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY,
63+
StandardWatchEventKinds.ENTRY_DELETE);
64+
65+
watcherThread = new WatcherThread(threadGroup, absoluteDirPath, detectingPath, watcher);
66+
threadIds.put(absoluteDirPath, watcherThread.getId());
67+
watcherThread.start();
68+
}
69+
}
70+
}
71+
72+
watcherThread.regist(fileListener);
73+
return true;
74+
} catch (IOException e) {
75+
logger.warn("IOException occur while registering file detecting.", e);
76+
return false;
77+
}
78+
}
79+
80+
public void remove(File file, String id) {
81+
if (file != null && StringUtils.hasText(id)) {
82+
Path detectingPath = getPathOrParentPath(file);
83+
WatcherThread thread = getThread(detectingPath.toAbsolutePath().toString(), true);
84+
if (thread != null) {
85+
thread.remove(id);
86+
}
87+
}
88+
}
89+
90+
public boolean isSubscribe(File file) {
91+
Path detectingPath = getPathOrParentPath(file);
92+
if (detectingPath == null) {
93+
return false;
94+
}
95+
96+
return getThread(detectingPath.toAbsolutePath().toString(), false) != null;
97+
}
98+
99+
private Path getPathOrParentPath(File file) {
100+
if (file == null) {
101+
return null;
102+
}
103+
104+
return (file.isDirectory()) ? file.toPath() : file.toPath().getParent();
105+
}
106+
107+
private WatcherThread getThread(String dirPath, boolean remove) {
108+
Long id = (remove) ? threadIds.remove(dirPath) : threadIds.get(dirPath);
109+
110+
if (id == null) {
111+
return null;
112+
}
113+
114+
Thread[] activeThreads = new Thread[threadGroup.activeCount()];
115+
threadGroup.enumerate(activeThreads);
116+
117+
for (Thread t : activeThreads) {
118+
if (id.longValue() == t.getId()) {
119+
return (WatcherThread) t;
120+
}
121+
}
122+
123+
return null;
124+
}
125+
126+
127+
private void initialize() {
128+
threadGroup = new ThreadGroup("FILE-WATCHER-THREADS");
129+
threadGroup.setDaemon(true);
130+
threadIds = new ConcurrentHashMap<>();
131+
132+
// TEMP
133+
Thread threadCheckTask = new Thread(() -> {
134+
try {
135+
while (!Thread.currentThread().isInterrupted()) {
136+
System.out.println("// ---------------------------------------------------");
137+
System.out.println("Check threads");
138+
System.out.println("Active thread count : " + threadGroup.activeCount());
139+
140+
Thread[] activeThreads = new Thread[threadGroup.activeCount()];
141+
threadGroup.enumerate(activeThreads);
142+
143+
for (Thread activeThread : activeThreads) {
144+
System.out.println(String.format("%s -- %s", activeThread.getId(), activeThread.getName()));
145+
}
146+
147+
System.out.println("------------------------------------------------------ //");
148+
TimeUnit.SECONDS.sleep(5);
149+
}
150+
} catch (InterruptedException e) {
151+
e.printStackTrace();
152+
}
153+
});
154+
threadCheckTask.setDaemon(true);
155+
threadCheckTask.start();
156+
// -- TEMP
157+
}
158+
159+
160+
private static class WatcherThread extends Thread {
161+
162+
private WatchService watcher;
163+
private Path path;
164+
private Map<String, FileListener> listeners;
165+
166+
public WatcherThread(ThreadGroup threadGroup, String threadName, Path path, WatchService watcher) {
167+
super(threadGroup, threadName);
168+
this.watcher = watcher;
169+
this.path = path;
170+
this.listeners = new ConcurrentHashMap<>();
171+
}
172+
173+
public FileListener regist(FileListener fileListener) {
174+
return listeners.put(fileListener.getIdentifier(), fileListener);
175+
}
176+
177+
public boolean isListen(String id) {
178+
return listeners.containsKey(id);
179+
}
180+
181+
public void remove(FileListener listener) {
182+
if (listener != null) {
183+
remove(listener.getIdentifier());
184+
}
185+
}
186+
187+
public void remove(String id) {
188+
listeners.remove(id);
189+
checkAndTerminate();
190+
191+
}
192+
193+
private void checkAndTerminate() {
194+
if (listeners.isEmpty()) {
195+
try {
196+
watcher.close();
197+
} catch (IOException e) {
198+
e.printStackTrace();
199+
this.interrupt();
200+
}
201+
}
202+
}
203+
204+
public void run() {
205+
try {
206+
while (!isInterrupted()) {
207+
WatchKey watchKey = watcher.take();
208+
209+
for (final WatchEvent<?> event : watchKey.pollEvents()) {
210+
final Kind<?> eventType = event.kind();
211+
final Path context = path.resolve((Path) event.context());
212+
213+
listeners.values().forEach(listener -> {
214+
if (listener.isHandle(eventType)) {
215+
listener.handleEvent(eventType, context);
216+
}
217+
});
218+
}
219+
220+
watchKey.reset();
221+
}
222+
} catch (InterruptedException e) {
223+
this.interrupt();
224+
} catch (ClosedWatchServiceException e) {
225+
// ignore
226+
}
227+
}
228+
}
229+
}

‎javademo/src/test/java/Temp.java‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import java.util.HashMap;
2+
import java.util.Map;
3+
import org.junit.Test;
4+
5+
/**
6+
* @author zacconding
7+
* @Date 2018年10月08日
8+
* @GitHub : https://github.com/zacscoding
9+
*/
10+
public class Temp {
11+
12+
@Test
13+
public void temp() {
14+
Map<String, String> map = new HashMap<>();
15+
map.put("1", "aa");
16+
System.out.println(map.put("1", "bb"));
17+
System.out.println(map.get("1"));
18+
}
19+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /