1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package demo;
20
21 import java.io.IOException;
22 import java.lang.management.ManagementFactory;
23 import java.nio.channels.FileChannel;
24 import java.nio.channels.FileLock;
25 import java.nio.file.FileStore;
26 import java.nio.file.Files;
27 import java.nio.file.Path;
28 import java.nio.file.Paths;
29 import java.nio.file.StandardOpenOption;
30 import java.util.concurrent.CountDownLatch;
31 import java.util.concurrent.atomic.AtomicInteger;
32
33
34
35
36
37
38
39
40
41 public class TestNioLock {
42 private static final int EC_WON = 10;
43
44 private static final int EC_LOST = 20;
45
46 private static final int EC_FAILED = 30;
47
48 private static final int EC_ERROR = 100;
49
50 public static void main(String[] args) throws IOException, InterruptedException {
51 if (args.length != 3) {
52 System.out.println("demo.TestNioLock <test|perform> <file> <sleepMs>");
53 System.exit(EC_ERROR);
54 }
55
56 String mode = args[0];
57 Path path = Paths.get(args[1]).toAbsolutePath();
58 Path latchFile = path.getParent().resolve(TestNioLock.class.getName() + ".latchFile");
59
60 if (Files.isDirectory(path)) {
61 System.out.println("The <file> cannot be directory.");
62 System.exit(EC_ERROR);
63 }
64 if (!Files.isRegularFile(latchFile)) {
65 Files.createFile(latchFile);
66 }
67
68 if ("test".equals(mode)) {
69 System.out.println("Testing file locking on");
70 System.out.println(
71 " Java " + System.getProperty("java.version") + ", " + System.getProperty("java.vendor"));
72 System.out.println(" OS " + System.getProperty("os.name") + " " + System.getProperty("os.version") + " "
73 + System.getProperty("os.arch"));
74
75 FileStore fileStore = Files.getFileStore(path.getParent());
76 System.out.println(" FS " + fileStore.name() + " " + fileStore.type());
77 System.out.println();
78
79 AtomicInteger oneResult = new AtomicInteger(-1);
80 AtomicInteger twoResult = new AtomicInteger(-1);
81 CountDownLatch latch = new CountDownLatch(2);
82 String javaCmd = System.getProperty("java.home") + "/bin/java";
83
84 try (FileChannel latchChannel =
85 FileChannel.open(latchFile, StandardOpenOption.READ, StandardOpenOption.WRITE)) {
86 try (FileLock latchLock = latchChannel.lock(0L, 1L, false)) {
87 new Thread(() -> {
88 try {
89 oneResult.set(new ProcessBuilder(
90 javaCmd, TestNioLock.class.getName(), "perform", args[1], args[2])
91 .inheritIO()
92 .start()
93 .waitFor());
94 } catch (Exception e) {
95 oneResult.set(EC_FAILED);
96 } finally {
97 latch.countDown();
98 }
99 })
100 .start();
101 new Thread(() -> {
102 try {
103 twoResult.set(new ProcessBuilder(
104 javaCmd, TestNioLock.class.getName(), "perform", args[1], args[2])
105 .inheritIO()
106 .start()
107 .waitFor());
108 } catch (Exception e) {
109 twoResult.set(EC_FAILED);
110 } finally {
111 latch.countDown();
112 }
113 })
114 .start();
115
116 Thread.sleep(1000);
117 latchLock.release();
118 latch.await();
119 }
120 }
121
122 int oneExit = oneResult.get();
123 int twoExit = twoResult.get();
124 if ((oneExit == EC_WON && twoExit == EC_LOST) || (oneExit == EC_LOST && twoExit == EC_WON)) {
125 System.out.println("OK");
126 System.exit(0);
127 } else {
128 System.out.println("FAILED: one=" + oneExit + " two=" + twoExit);
129 System.exit(EC_FAILED);
130 }
131 } else if ("perform".equals(mode)) {
132 String processName = ManagementFactory.getRuntimeMXBean().getName();
133 System.out.println(processName + " > started");
134 boolean won = false;
135 long sleepMs = Long.parseLong(args[2]);
136 try (FileChannel latchChannel = FileChannel.open(latchFile, StandardOpenOption.READ)) {
137 try (FileLock latchLock = latchChannel.lock(0L, 1L, true)) {
138 System.out.println(processName + " > latchLock acquired");
139 try (FileChannel channel = FileChannel.open(
140 path, StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE)) {
141 try (FileLock lock = channel.tryLock(0L, 1L, false)) {
142 if (lock != null && lock.isValid() && !lock.isShared()) {
143 System.out.println(processName + " > WON");
144 won = true;
145 Thread.sleep(sleepMs);
146 } else {
147 System.out.println(processName + " > LOST");
148 }
149 }
150 }
151 }
152 }
153 System.out.println(processName + " > ended");
154 if (won) {
155 System.exit(EC_WON);
156 } else {
157 System.exit(EC_LOST);
158 }
159 } else {
160 System.err.println("Unknown mode: " + mode);
161 }
162 System.exit(EC_ERROR);
163 }
164 }