diff --git a/.gitignore b/.gitignore index a98a8a6..9201f3c 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,5 @@ target/ .DS_Store Thumbs.db *.orig + +.vs diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/pom.xml" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/pom.xml" index 53915ce..cb7c659 100644 --- "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/pom.xml" +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/pom.xml" @@ -12,6 +12,9 @@ stage-1 stage-2 + stage-3 + stage-4 + stage-5 diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/lesson-3/pom.xml" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/lesson-3/pom.xml" index fbb2124..fc7874f 100644 --- "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/lesson-3/pom.xml" +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/lesson-3/pom.xml" @@ -9,7 +9,7 @@ ../pom.xml 4.0.0 - 「一入 Java 深似海 」系列 :: 第二期 :: 第二节 + 「一入 Java 深似海 」系列 :: 第二期 :: 第三节 stage-2-lesson-3 diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/lesson-4/pom.xml" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/lesson-4/pom.xml" index 8bd4318..812cd95 100644 --- "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/lesson-4/pom.xml" +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/lesson-4/pom.xml" @@ -8,7 +8,7 @@ 1.0-SNAPSHOT 4.0.0 - + 「一入 Java 深似海 」系列 :: 第二期 :: 第三节 stage-2-lesson-4 diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/lesson-4/src/main/java/com/segmentfault/deep/in/java/collection/algorithm/BubbleSort.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/lesson-4/src/main/java/com/segmentfault/deep/in/java/collection/algorithm/BubbleSort.java" index ea9f2f9..ccc372e 100644 --- "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/lesson-4/src/main/java/com/segmentfault/deep/in/java/collection/algorithm/BubbleSort.java" +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/lesson-4/src/main/java/com/segmentfault/deep/in/java/collection/algorithm/BubbleSort.java" @@ -16,22 +16,26 @@ public void sort(T[] values) { // Given array : [3,1,2,5,4] // for 1 | // for 2 | - for (int i = 0; i < size; i++) { - // 第 i 号元素 - T t = values[i]; // 产生临时变量 - for (int j = i + 1; j < size; j++) { - // 第 i 号元素与 i + 1 对比 - if (t.compareTo(values[j]) == 1) { // 低位 > 高位 - // 交换元素 [i + 1] = [i] - values[i] = values[j]; - values[j] = t; - // [0] = 3 , [1] = 2 - // [1] = [1](2) + [0](3) = 5 - // [0] = [1](5) - [0](3) = 2 - // [1] = [1](5) - [0](2) = 3 - break; + int count = size - 1; + while ( count >= 0) { + for (int i = 0; i < size; i++) { + // 第 i 号元素 + T t = values[i]; // 产生临时变量 + for (int j = i + 1; j < size; j++) { + // 第 i 号元素与 i + 1 对比 + if (t.compareTo(values[j]) == 1) { // 低位 > 高位 + // 交换元素 [i + 1] = [i] + values[i] = values[j]; + values[j] = t; + // [0] = 3 , [1] = 2 + // [1] = [1](2) + [0](3) = 5 + // [0] = [1](5) - [0](3) = 2 + // [1] = [1](5) - [0](2) = 3 + break; + } } } + count--; } } diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/lesson-4/src/main/java/com/segmentfault/deep/in/java/collection/algorithm/InsertionSort.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/lesson-4/src/main/java/com/segmentfault/deep/in/java/collection/algorithm/InsertionSort.java" index 15c93e7..ace9cc4 100644 --- "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/lesson-4/src/main/java/com/segmentfault/deep/in/java/collection/algorithm/InsertionSort.java" +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/lesson-4/src/main/java/com/segmentfault/deep/in/java/collection/algorithm/InsertionSort.java" @@ -1,6 +1,6 @@ package com.segmentfault.deep.in.java.collection.algorithm; -import java.util.stream.Stream; +import java.util.Arrays; public class InsertionSort> implements Sort { @@ -17,20 +17,30 @@ public void sort(T[] values) { // [j = 0] = 3, [i = 1] = 1 , t = [i = 1] = 1 // [i = 1] = [j = 0] , [j = 0] = t = 1 T t = values[i]; // 产生临时变量 - for (int j = i - 1; j >= 0; j--) { - if (t.compareTo(values[j]) < 1) { // 高位 < 低位 - values[i] = values[j]; // 高位获取低位的值 - values[j] = t; // 低位得到高位的值 - } + int j = i; + while (j > 0 && t.compareTo(values[j - 1]) < 0) { + //往后移动让出插入空间 + values[j] = values[j - 1]; + j--; } + //插入values[i]到对应位置 + values[j] = t; + System.out.printf("第%d轮:%s\n", i, Arrays.toString(values)); } } public static void main(String[] args) { - Integer[] values = Sort.of(3, 1, 2, 5, 4); - Sort sort = new InsertionSort<>(); // Java 7 Diamond 语法 + System.out.println("一般情况"); + Integer[] values = Sort.of(3, 2, 1, 5, 4); + Sort sort = new InsertionSort<>(); sort.sort(values); - Stream.of(values).forEach(System.out::println); + System.out.println(Arrays.toString(values)); + + System.out.println("完全逆序"); + values = Sort.of(5, 4, 3, 2, 1); + sort = new InsertionSort<>(); + sort.sort(values); + System.out.println(Arrays.toString(values)); } } diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/lesson-4/src/main/java/com/segmentfault/deep/in/java/collection/algorithm/MergeSort.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/lesson-4/src/main/java/com/segmentfault/deep/in/java/collection/algorithm/MergeSort.java" index 30ce7fd..943ec33 100644 --- "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/lesson-4/src/main/java/com/segmentfault/deep/in/java/collection/algorithm/MergeSort.java" +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/lesson-4/src/main/java/com/segmentfault/deep/in/java/collection/algorithm/MergeSort.java" @@ -26,7 +26,7 @@ private void merge(Comparable[] values, int low, int mid, int high) { Comparable[] a2 = new Comparable[n2]; //把 values[0...mid] 内容复制给 a1 - System.arraycopy(values, 0, a1, 0, n1); + System.arraycopy(values, low, a1, 0, n1); //把 values[mid+1...high] 内容复制给 a2 System.arraycopy(values, mid + 1, a2, 0, n2); diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/lesson-4/src/main/java/com/segmentfault/deep/in/java/collection/algorithm/QuickSort.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/lesson-4/src/main/java/com/segmentfault/deep/in/java/collection/algorithm/QuickSort.java" index bc68f67..8304c19 100644 --- "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/lesson-4/src/main/java/com/segmentfault/deep/in/java/collection/algorithm/QuickSort.java" +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/lesson-4/src/main/java/com/segmentfault/deep/in/java/collection/algorithm/QuickSort.java" @@ -1,5 +1,6 @@ package com.segmentfault.deep.in.java.collection.algorithm; +import java.util.Arrays; import java.util.stream.Stream; public class QuickSort> implements Sort { @@ -63,28 +64,28 @@ int partition(T[] values, int low, int high) { // pIndex = 3 T pivot = values[high]; - int i = low - 1; + int i = low; for (int j = low; j < high; j++) { if (values[j].compareTo(pivot) < 1) { // <= - i++; // -1 -> 0 T temp = values[i]; // 低位数据 values[i] = values[j]; // 低位数据获取高位数据 values[j] = temp; + i++; // -1 -> 0 } } - T temp = values[i + 1]; - values[i + 1] = values[high]; + T temp = values[i]; + values[i] = values[high]; values[high] = temp; - return i + 1; // 游标+1 + return i; } public static void main(String[] args) { - Integer[] values = Sort.of(3, 1, 2, 5, 4); + Integer[] values = Sort.of(2, 5, 6, 7, 8, 8, 9, 2, 1, 6, 7, 5, 6, 11, 23); Sort sort = new QuickSort<>(); // Java 7 Diamond 语法 sort.sort(values); - Stream.of(values).forEach(System.out::println); + System.out.println(Arrays.asList(values)); } } diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/pom.xml" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/pom.xml" index 9913bf8..76b1fe3 100644 --- "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/pom.xml" +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-2/pom.xml" @@ -16,7 +16,7 @@ lesson-1 lesson-2 lesson-3 - stage-2-lesson-4 + lesson-4 diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/pom.xml" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/pom.xml" new file mode 100644 index 0000000..fe88fd6 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/pom.xml" @@ -0,0 +1,35 @@ + + + + deep-in-java + com.segmentfault + 1.0-SNAPSHOT + + 4.0.0 + + stage-3 + 「一入 Java 深似海 」系列 :: 第三期 + + stage-3-lesson-1 + stage-3-lesson-2 + stage-3-lesson-3 + stage-3-lesson-4 + + pom + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 11 + 11 + + + + + \ No newline at end of file diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/pom.xml" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/pom.xml" new file mode 100644 index 0000000..33b78be --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/pom.xml" @@ -0,0 +1,15 @@ + + + + stage-3 + com.segmentfault + 1.0-SNAPSHOT + + 4.0.0 + 「一入 Java 深似海 」系列 :: 第三期 :: 第一节 + stage-3-lesson-1 + + + \ No newline at end of file diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/process/ChildProcessDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/process/ChildProcessDemo.java" new file mode 100644 index 0000000..12846c4 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/process/ChildProcessDemo.java" @@ -0,0 +1,29 @@ +package com.segmentfault.deep.in.java.process; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.management.ManagementFactory; +import java.lang.management.OperatingSystemMXBean; + +public class ChildProcessDemo { + + public static void main(String[] args) throws IOException { + + // IDEA(主进程) -> 启动 ChildProcessDemo -> Windows 计算器(calc) + OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean(); + + if (operatingSystemMXBean.getName().startsWith("Windows")) { + // 启动计算器 + Runtime.getRuntime().exec("calc"); + +// Process process = Runtime.getRuntime().exec("dir"); +// +// InputStream inputStream = process.getInputStream(); +// int data = 0; +// while ((data = inputStream.read()) > -1) { +// System.out.print(data); +// } + } + + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/process/ProcessExecutor.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/process/ProcessExecutor.java" new file mode 100644 index 0000000..23d0139 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/process/ProcessExecutor.java" @@ -0,0 +1,134 @@ +package com.segmentfault.deep.in.java.process; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.concurrent.TimeoutException; + +/** + * https://github.com/mercyblitz/confucius-commons + */ +public class ProcessExecutor { + + private static final long waitForTimeInSecond = Long.getLong("process.executor.wait.for", 1); + private final String command; + private final String arguments; + private final Runtime runtime = Runtime.getRuntime(); + private boolean finished; + + /** + * Constructor + * + * @param processName + * command + * @param arguments + * process arguments + */ + public ProcessExecutor(String processName, String... arguments) { + StringBuilder argumentsBuilder = new StringBuilder(); + if (arguments != null) { + for (String argument : arguments) { + argumentsBuilder.append(" ").append(argument); + } + } + this.arguments = argumentsBuilder.toString(); + this.command = processName + this.arguments; + } + + /** + * Execute current process. + *

+ * // * @param inputStream input stream keeps output stream from process + * + * @param outputStream + * output stream for process normal or error input stream. + * @throws IOException + * if process execution is failed. + */ + public void execute(OutputStream outputStream) throws IOException { + try { + this.execute(outputStream, Long.MAX_VALUE); + } catch (TimeoutException e) { + } + } + + /** + * Execute current process. + *

+ * // * @param inputStream input stream keeps output stream from process + * + * @param outputStream + * output stream for process normal or error input stream. + * @param timeoutInMilliseconds + * milliseconds timeout + * @throws IOException + * if process execution is failed. + * @throws TimeoutException + * if the execution is timeout over specified timeoutInMilliseconds + */ + public void execute(OutputStream outputStream, long timeoutInMilliseconds) throws IOException, TimeoutException { + Process process = runtime.exec(command); + long startTime = System.currentTimeMillis(); + long endTime = -1L; + InputStream processInputStream = process.getInputStream(); + InputStream processErrorInputStream = process.getErrorStream(); +// OutputStream processOutputStream = process.getOutputStream(); + int exitValue = -1; + while (!finished) { + long costTime = endTime - startTime; + if (costTime > timeoutInMilliseconds) { + finished = true; + process.destroy(); + String message = String.format("Execution is timeout[%d ms]!", timeoutInMilliseconds); + throw new TimeoutException(message); + } + try { + while (processInputStream.available() > 0) { + outputStream.write(processInputStream.read()); + } + while (processErrorInputStream.available() > 0) { + outputStream.write(processErrorInputStream.read()); + } + exitValue = process.exitValue(); + if (exitValue != 0) { + throw new IOException(); + } + finished = true; + } catch (IllegalThreadStateException e) { + // Process is not finished yet; + // Sleep a little to save on CPU cycles + waitFor(waitForTimeInSecond); + endTime = System.currentTimeMillis(); + } finally { + } + } + } + + /** + * Wait for specified seconds + * + * @param seconds + * specified seconds + */ + private void waitFor(long seconds) { + try { + Thread.sleep(seconds * 1000); + } catch (InterruptedException e) { + Thread.interrupted(); + } + } + + /** + * Check current process finish or not. + * + * @return true if current process finished + */ + public boolean isFinished() { + return finished; + } + + public static void main(String[] args) throws IOException, TimeoutException { + ProcessExecutor executor = new ProcessExecutor("java","-version"); + executor.execute(System.out, 2000); + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/process/ProcessIdDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/process/ProcessIdDemo.java" new file mode 100644 index 0000000..5cdd49e --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/process/ProcessIdDemo.java" @@ -0,0 +1,32 @@ +package com.segmentfault.deep.in.java.process; + +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; + +public class ProcessIdDemo { + + public static void main(String[] args) { + + // Java 9 之前的实现 + getProcessIdBeforeJava9(); + getProcessIdInJava9(); + getProcessIdInJava10(); + } + + private static void getProcessIdInJava10() { + RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean(); + System.out.println("[Java 10 + 的方法] 当前进程 ID : " + runtimeMXBean.getPid()); + } + + private static void getProcessIdInJava9() { + long pid = ProcessHandle.current().pid(); + System.out.println("[Java 9 + 的方法] 当前进程 ID : " + pid); + } + + private static void getProcessIdBeforeJava9() { + RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean(); + String name = runtimeMXBean.getName(); + String pid = name.substring(0, name.indexOf("@")); + System.out.println("[Java 9 之前的方法] 当前进程 ID : " + pid); + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/process/ProcessInfoDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/process/ProcessInfoDemo.java" new file mode 100644 index 0000000..907e345 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/process/ProcessInfoDemo.java" @@ -0,0 +1,31 @@ +package com.segmentfault.deep.in.java.process; + +import java.lang.management.*; +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneId; + +public class ProcessInfoDemo { + + public static void main(String[] args) { + + RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean(); + ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); + OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean(); + + long pid = ProcessHandle.current().pid(); + System.out.println("[Java 9 + 的方法] 当前进程 ID : " + pid); + + Instant instant = Instant.ofEpochMilli(runtimeMXBean.getStartTime()); + LocalDate localDate = LocalDate.ofInstant(instant, ZoneId.systemDefault()); + System.out.println("当前进程启动时间:" + localDate); + System.out.println("当前进程上线时间:" + runtimeMXBean.getUptime()); + System.out.println("当前进程线程数量:" + threadMXBean.getThreadCount()); + + ManagementFactory.getMemoryManagerMXBeans().forEach(memoryManagerMXBean -> { + + }); + + System.exit(9); + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/thread/DumpThreadDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/thread/DumpThreadDemo.java" new file mode 100644 index 0000000..0630e5f --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/thread/DumpThreadDemo.java" @@ -0,0 +1,17 @@ +package com.segmentfault.deep.in.java.thread; + +public class DumpThreadDemo { + + public static void main(String[] args) { + + // Throwable API + new Throwable("Stack trace").printStackTrace(System.out); + + // Thread API + Thread.dumpStack(); + + // Java 9 StackWalker API + StackWalker stackWalker = StackWalker.getInstance(); + stackWalker.forEach(System.out::println); + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/thread/HowToStopThreadDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/thread/HowToStopThreadDemo.java" new file mode 100644 index 0000000..725399c --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/thread/HowToStopThreadDemo.java" @@ -0,0 +1,47 @@ +package com.segmentfault.deep.in.java.thread; + +import java.util.concurrent.Executors; + +public class HowToStopThreadDemo { + + public static void main(String[] args) throws InterruptedException { + + StoppableAction action = new StoppableAction(); + + Thread thread = new Thread(action); + + // 线程启动(并不一定执行) + thread.start(); + + // main 线程调整 stopped 状态到 true + action.stop(); + + // 如果线程池的话,以上方案可能存在问题 + Executors.newFixedThreadPool(2); // 有且只有2个线程在复用 + Executors.newCachedThreadPool(); // 几乎无限数量线程 + } + + private static class StoppableAction implements Runnable { + + /** + * 确保 stopped 原子操作,等价于 AtomicBoolean + */ + private volatile boolean stopped; + + @Override + public void run() { + + if (stopped) { + // 通过异常的方式,可以 Kill 线程 + System.out.println("Action 中止..."); + return; + } + + System.out.println("Action 执行..."); + } + + public void stop() { + this.stopped = true; + } + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/thread/ThreadDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/thread/ThreadDemo.java" new file mode 100644 index 0000000..031be2a --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/thread/ThreadDemo.java" @@ -0,0 +1,18 @@ +package com.segmentfault.deep.in.java.thread; + +public class ThreadDemo { + + public static void main(String[] args) throws InterruptedException { + // Thread 实现 Runnable + // 如果没有传递 Runnable 对象实现,空执行 + Thread thread = new Thread(ThreadDemo::sayHelloWorld); // 方法引用 + thread.start(); // 启动线程 + thread.join(); // 等待线程结束 + System.out.println("Hello Next..."); + System.out.print(thread.getState()); + } + + public static void sayHelloWorld() { + System.out.printf("线程 [Id : %s] : Hello,World!\n", Thread.currentThread().getId()); + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/thread/ThreadInterruptDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/thread/ThreadInterruptDemo.java" new file mode 100644 index 0000000..648fa9f --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/thread/ThreadInterruptDemo.java" @@ -0,0 +1,39 @@ +package com.segmentfault.deep.in.java.thread; + +public class ThreadInterruptDemo { + + public static void main(String[] args) throws InterruptedException { + // Thread 实现 Runnable + // 如果没有传递 Runnable 对象实现,空执行 + Thread thread = new Thread(ThreadInterruptDemo::sayHelloWorld); // 方法引用 + // thread.interrupt() 方法在 start() 调用之前是没有效果 + thread.start(); // 启动线程 + thread.interrupt(); // main 线程 interrupt 子线程 + // interrupt() 并不能中止线程,但是可以传递 interrupt 状态 + thread.join(); // 等待线程结束 + } + + public static void sayHelloWorld() { + + if (Thread.currentThread().isInterrupted()) { + System.out.printf("线程 [Id : %s] 被中止!\n", Thread.currentThread().getId()); + return; + } + + Object monitor = ThreadInterruptDemo.class; + + synchronized (monitor) { + try { + monitor.wait(1000); + } catch (InterruptedException e) { + // 当前 interrupted 状态被清除 == false + e.printStackTrace(); + System.out.printf("线程 [Id : %s] 当前 interrupted 状态 = %s\n", + Thread.currentThread().getId(), Thread.currentThread().isInterrupted()); + return; + } + } + + System.out.printf("线程 [Id : %s] : Hello,World!\n", Thread.currentThread().getId()); + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/thread/ThreadSuspendAndResumeDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/thread/ThreadSuspendAndResumeDemo.java" new file mode 100644 index 0000000..c058083 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/thread/ThreadSuspendAndResumeDemo.java" @@ -0,0 +1,11 @@ +package com.segmentfault.deep.in.java.thread; + +public class ThreadSuspendAndResumeDemo { + + public static void main(String[] args) { + // Thread.suspend() 和 Thread.resume() 方法可以运用任意区域 + // suspend():指定线程挂起,resume():指定线程恢复 + // Object.wait() 和 Object.notify() 只能用在 synchronized 方法或块 + // 通过对象 Monitor 控制线程状态 + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/thread/ThreadWaitAndNotifyDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/thread/ThreadWaitAndNotifyDemo.java" new file mode 100644 index 0000000..11deb01 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-1/src/main/java/com/segmentfault/deep/in/java/thread/ThreadWaitAndNotifyDemo.java" @@ -0,0 +1,62 @@ +package com.segmentfault.deep.in.java.thread; + +public class ThreadWaitAndNotifyDemo { + + public static void main(String[] args) throws InterruptedException { + // Thread 实现 Runnable + // 如果没有传递 Runnable 对象实现,空执行 + // wait() 语义:在同步(互斥)场景下 + + // Lock 场景: T1、T2,互斥访问资源 R + // T1 获取 L(T1) -> T2 获取 L(T2) + // T1.wait() T2.wait() 都要被阻塞(停顿) + Thread t1 = new Thread(ThreadWaitAndNotifyDemo::sayHelloWorld); // 方法引用 + t1.setName("T1"); + t1.start(); // 启动线程 + + Thread t2 = new Thread(ThreadWaitAndNotifyDemo::sayHelloWorld); + t2.setName("T2"); + t2.start(); + + // Object.wait() 与 Thread.join() 看起来效果类似 + // 实际上 Thread.join() 方法就是调用了 Thread 对象 wait(int) 方法 + + // 调用 wait() 方法的对象,再调用 notify() 方法必须是同一对象 + // 因此以下调用时错误的示范 + Object monitor = ThreadWaitAndNotifyDemo.class; + synchronized (monitor) { +// t1.notify(); +// t2.notify(); + } + + // 正确的写法: + synchronized (monitor) { + // 为什么 monitor.notify() 不能保证完全释放 + // monitor.notify(); + monitor.notifyAll(); + } + + // 第三方可以(条件)控制 T1 或者 T2 释放 + + // Java 5+ : Condition 条件,await() 等待,signal() 通知 + } + + public static void sayHelloWorld() { + + Thread currentThread = Thread.currentThread(); + + Object monitor = ThreadWaitAndNotifyDemo.class; + + synchronized (monitor) { + try { + System.out.printf("线程[%s] 进入等待状态...\n", currentThread.getName()); + monitor.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.printf("线程[%s] 恢复执行...\n", currentThread.getName()); + System.out.printf("线程[%s] : Hello,World!\n", currentThread.getName()); + } + } + +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-2/pom.xml" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-2/pom.xml" new file mode 100644 index 0000000..1747649 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-2/pom.xml" @@ -0,0 +1,15 @@ + + + + stage-3 + com.segmentfault + 1.0-SNAPSHOT + + 4.0.0 + + stage-3-lesson-2 + 「一入 Java 深似海 」系列 :: 第三期 :: 第二节 + + \ No newline at end of file diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-2/src/main/java/com/segmentfault/deep/in/java/concurrency/DeadLockDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-2/src/main/java/com/segmentfault/deep/in/java/concurrency/DeadLockDemo.java" new file mode 100644 index 0000000..0fefb70 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-2/src/main/java/com/segmentfault/deep/in/java/concurrency/DeadLockDemo.java" @@ -0,0 +1,43 @@ +package com.segmentfault.deep.in.java.concurrency; + +public class DeadLockDemo { + + public static void main(String[] args) { + + final Object m1 = new Object(); + final Object m2 = new Object(); + + new Thread(() -> { + synchronized (m1) { + System.out.printf("Thread[ ID : %d] holds m1\n", Thread.currentThread().getId()); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + synchronized (m2) { + System.out.printf("Thread[ ID : %d] holds m2\n", Thread.currentThread().getId()); + } + } + }).start(); + + new Thread(() -> { + synchronized (m2) { + System.out.printf("Thread[ ID : %d] holds m2\n", Thread.currentThread().getId()); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + synchronized (m1) { + System.out.printf("Thread[ ID : %d] holds m1\n", Thread.currentThread().getId()); + } + } + }).start(); + + + + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-2/src/main/java/com/segmentfault/deep/in/java/concurrency/ProducerConsumerProblemDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-2/src/main/java/com/segmentfault/deep/in/java/concurrency/ProducerConsumerProblemDemo.java" new file mode 100644 index 0000000..784f615 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-2/src/main/java/com/segmentfault/deep/in/java/concurrency/ProducerConsumerProblemDemo.java" @@ -0,0 +1,83 @@ +package com.segmentfault.deep.in.java.concurrency; + +import java.util.LinkedList; +import java.util.List; +import java.util.Random; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +public class ProducerConsumerProblemDemo { + + public static void main(String[] args) throws ExecutionException, InterruptedException { + + ExecutorService executorService = Executors.newFixedThreadPool(2); + + Container container = new Container(); + + Future producerFuture = executorService.submit(() -> { // 生产者线程 + container.produce(); + }); + + Future consumerFuture = executorService.submit(() -> { // 消费者线程 + container.consume(); + }); + + + Thread.sleep(1000L); + + executorService.shutdown(); + } + + public static class Container { + + private List data = new LinkedList<>(); + + private static final int MAX_SIZE = 5; + + private Random random = new Random(); + + public void produce() { + while (true) { // 永久执行 + synchronized (this) { + try { + // 当数据超过上限 MAX_SIZE,停止生产 + while (data.size() >= MAX_SIZE) { + wait(); + } + int value = random.nextInt(100); + System.out.printf("线程[%s] 正在生产数据 : %d\n", Thread.currentThread().getName(), value); + data.add(value); + + // 唤起消费线程 + notify(); + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + + public void consume() { + while (true) { // 永久执行 + synchronized (this) { + try { + // 当数据没有时,停止消费 + while (data.isEmpty()) { + wait(); + } + int value = data.remove(0); + System.out.printf("线程[%s] 正在消费数据 : %d\n", Thread.currentThread().getName(), value); + // 唤起消费线程 + notify(); + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-2/src/main/java/com/segmentfault/deep/in/java/concurrency/SynchronizedDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-2/src/main/java/com/segmentfault/deep/in/java/concurrency/SynchronizedDemo.java" new file mode 100644 index 0000000..4ad2bc8 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-2/src/main/java/com/segmentfault/deep/in/java/concurrency/SynchronizedDemo.java" @@ -0,0 +1,39 @@ +package com.segmentfault.deep.in.java.concurrency; + +public class SynchronizedDemo { + + public static void main(String[] args) { + + synchronized (SynchronizedDemo.class) { + + + } + + new Thread().start(); + } + + private static void changeValue(int value) { + // 线程私有对象,尽管它也在堆里面 + // 栈保存 value 名称,data 变量名称 + // 堆共享(被其他线程可见)是线程不安全的,保存内存 + // 当线程不加以控制数量的话,容易导致 JVM OOM + Data data = new Data(); + data.setValue(1); + } + + private static class Data { + + /** + * 线程不安全 + */ + private volatile int value; + + public int getValue() { + return value; + } + + public void setValue(int value) { + this.value = value; + } + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-2/src/main/java/com/segmentfault/deep/in/java/concurrency/SynchronizedMethodAndBlockDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-2/src/main/java/com/segmentfault/deep/in/java/concurrency/SynchronizedMethodAndBlockDemo.java" new file mode 100644 index 0000000..6cc44e8 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-2/src/main/java/com/segmentfault/deep/in/java/concurrency/SynchronizedMethodAndBlockDemo.java" @@ -0,0 +1,32 @@ +package com.segmentfault.deep.in.java.concurrency; + +public class SynchronizedMethodAndBlockDemo { + + public static void main(String[] args) { + // synchronized 保证互斥 + // 当某个线程 T1 获得锁(1),重新又见到 synchronized(+1) + // 以此类推 + echo("Hello,World"); // echo 到底重进入了多少次?3 + // echo -> PrintStream.println -> newLine() + doEcho("Hello,World"); // doEcho 到底重进入了多少次?4 + // doEcho -> echo -> PrintStream.println -> newLine() + } + + private static void doEcho(String message) { + Object object = new Object(); + synchronized (object) { + // wait 和 notify + echo(message); + } + } + + /** + * synchronized 修饰方法(实例或类) + * + * @param message + */ + private synchronized static void echo(String message) { + System.out.println(message); + } + +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-2/src/main/java/com/segmentfault/deep/in/java/concurrency/SynchronizedObjectAndClassDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-2/src/main/java/com/segmentfault/deep/in/java/concurrency/SynchronizedObjectAndClassDemo.java" new file mode 100644 index 0000000..dfae756 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-2/src/main/java/com/segmentfault/deep/in/java/concurrency/SynchronizedObjectAndClassDemo.java" @@ -0,0 +1,26 @@ +package com.segmentfault.deep.in.java.concurrency; + +public class SynchronizedObjectAndClassDemo { + + public static void main(String[] args) { + + Object object = new Object(); + + // 对象锁 + synchronized (object) { // Monitor -> Object + // 对象存在在 Heap(堆) + // ... + } + + // 类锁 + synchronized (Object.class) { + // 类对象存在于 Metadata区域(Java 8+) + // 或者 Perm 区域(<= Java 7)方法区 + // ... + } + + // Class 对象就是 Object 实例 + Object objectClass = Object.class; + + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-2/src/main/java/com/segmentfault/deep/in/java/concurrency/SynchronizedPerformanceDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-2/src/main/java/com/segmentfault/deep/in/java/concurrency/SynchronizedPerformanceDemo.java" new file mode 100644 index 0000000..4fcd4a8 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-2/src/main/java/com/segmentfault/deep/in/java/concurrency/SynchronizedPerformanceDemo.java" @@ -0,0 +1,38 @@ +package com.segmentfault.deep.in.java.concurrency; + +import java.util.ArrayList; +import java.util.List; +import java.util.Vector; +import java.util.function.Consumer; + +public class SynchronizedPerformanceDemo { + + public static void main(String[] args) { + // 对比 Vector 和 ArrayList + // 相同点:两者都使用数组(Array)作为存储,集合算法类似 + Vector vector = new Vector(); + ArrayList list = new ArrayList(); + + doTest(10000, vector); + doTest(10000, list); + + System.gc(); + + doTest(100000, vector); + doTest(100000, list); + + System.gc(); + + } + + + private static void doTest(int count, List list) { + long startTime = System.currentTimeMillis(); + for (int i = 0; i < count; i++) { + list.add(new Object()); + } + long costTime = System.currentTimeMillis() - startTime; + System.out.printf("%s add costing %f ms(avg)\n", list.getClass().getName(), costTime / (count * 1.0)); + } + +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-2/src/main/java/com/segmentfault/deep/in/java/concurrency/ThreadStarvationDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-2/src/main/java/com/segmentfault/deep/in/java/concurrency/ThreadStarvationDemo.java" new file mode 100644 index 0000000..43d35ec --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-2/src/main/java/com/segmentfault/deep/in/java/concurrency/ThreadStarvationDemo.java" @@ -0,0 +1,12 @@ +package com.segmentfault.deep.in.java.concurrency; + +public class ThreadStarvationDemo { + + public static void main(String[] args) { + new ThreadStarvationDemo(); + } + + public void finalize() { // FinalReference + System.out.printf("Thread[%s] executes current object's finalization.\n", Thread.currentThread().getName()); + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/pom.xml" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/pom.xml" new file mode 100644 index 0000000..b7a2dc4 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/pom.xml" @@ -0,0 +1,15 @@ + + + + stage-3 + com.segmentfault + 1.0-SNAPSHOT + + 4.0.0 + + stage-3-lesson-3 + 「一入 Java 深似海 」系列 :: 第三期 :: 第三节 + + \ No newline at end of file diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/src/main/java/com/segmentfault/deep/in/java/concurrency/AcquireAndReleaseDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/src/main/java/com/segmentfault/deep/in/java/concurrency/AcquireAndReleaseDemo.java" new file mode 100644 index 0000000..5c649cc --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/src/main/java/com/segmentfault/deep/in/java/concurrency/AcquireAndReleaseDemo.java" @@ -0,0 +1,22 @@ +package com.segmentfault.deep.in.java.concurrency; + +public class AcquireAndReleaseDemo { + + public static void main(String[] args) { + // Lock 机制 + // 获得 Acquire + // Thread 进入 synchronized -> 获得锁 + // 释放 Release + // 1. 当 Thread(hold lock),调用 Object#wait() 时候 + // 2. Thread park -> LockSupport.park(Object) + // 3. Condition#await() + // 4. 运行期异常,Thread 消亡 + // 5. Java 9 自旋 Thread.onSpinWait(); + // 6. Thread.yield(); + + // 所谓的公平(Fair)和非公平(Nonfair、unfair) + // 公平(Fair)线程 FIFO + // 非公平(Nonfair)线程随线程调度 + // 最佳实践:在创建线程时,除非必要,不要调整线程优先级(Priority) + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/src/main/java/com/segmentfault/deep/in/java/concurrency/AtomicDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/src/main/java/com/segmentfault/deep/in/java/concurrency/AtomicDemo.java" new file mode 100644 index 0000000..6a8bc23 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/src/main/java/com/segmentfault/deep/in/java/concurrency/AtomicDemo.java" @@ -0,0 +1,69 @@ +package com.segmentfault.deep.in.java.concurrency; + +import sun.misc.Unsafe; + +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import java.lang.reflect.Field; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; + +public class AtomicDemo { + + public static void main(String[] args) throws Exception { + // CAS 是一种相对(MB)较重的比较,轻量级的锁(标量) + + getUnsafe(); + + // volatile 修饰复杂对象类型时,不具备被传递到字段安全 + } + + private static void demoAtomicLong() { + // long 表示 64位(8字节),高和低两端 + // long 并非线程安全,就是 volatile(高和低操作时,至少两次操作) + AtomicLong l = new AtomicLong(); + // set 和 get 通过 JVM 特殊操作,不在直接写入和获取 + } + + private static void demoAtomicInteger() { + // int 表示 int(32), char(16), short(16), byte(8), boolean(1) + // AtomicInteger 内部使用 int 作为变量标识,1 表示 true, 0 表示 false + // AtomicInteger set 和 get 操作均为 volatile 语义(MB) + // AtomicInteger CAS Unsafe(Java 8) 和 VarHandle(Java 9+) + } + + private static void demoAtomicBoolean() { + AtomicBoolean b = new AtomicBoolean(); + // AtomicBoolean 内部使用 int 作为变量标识,1 表示 true, 0 表示 false + // AtomicBoolean set 和 get 操作均为 volatile 语义(MB) + // AtomicBoolean CAS Unsafe(Java 8) 和 VarHandle(Java 9+) + } + + private static void getVarHandle() { + MethodHandles.Lookup l = MethodHandles.lookup(); + } + + private static void getUnsafe() throws PrivilegedActionException { + // 无法通过正常方法调用 +// Unsafe unsafe = Unsafe.getUnsafe(); + + // https://github.com/mercyblitz/confucius-commons/blob/master/confucius-commons-lang/src/main/java/org/confucius/commons/lang/misc/UnsafeUtils.java + final PrivilegedExceptionAction action = new PrivilegedExceptionAction() { + public Unsafe run() throws Exception { + Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafe.setAccessible(true); + return (Unsafe) theUnsafe.get(null); + } + }; + + Unsafe unsafe = AccessController.doPrivileged(action); + + if (unsafe == null) { + throw new NullPointerException(); + } + + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/src/main/java/com/segmentfault/deep/in/java/concurrency/CountDownLatchDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/src/main/java/com/segmentfault/deep/in/java/concurrency/CountDownLatchDemo.java" new file mode 100644 index 0000000..2d04c6b --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/src/main/java/com/segmentfault/deep/in/java/concurrency/CountDownLatchDemo.java" @@ -0,0 +1,40 @@ +package com.segmentfault.deep.in.java.concurrency; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class CountDownLatchDemo { + + public static void main(String[] args) throws InterruptedException { + // 4 -> 3 -> 2 -> 1 + CountDownLatch latch = new CountDownLatch(4); // 4 个计数 + ExecutorService executorService = Executors.newFixedThreadPool(3); // 线程数 3 + + for (int i = 0; i < 3; i++) { // 启动3个线程 + executorService.submit(() -> { + try { + echoThread(); + latch.countDown(); // -1 + } catch (Exception e) { + e.printStackTrace(); + } + }); + } + + Thread.sleep(5 * 100); + + // 当 count 数量等于 0,才会释放 + // 4-3 == 1 !=0 + System.out.println("CountDownLatch 剩余数量:" + latch.getCount()); + latch.await(); // await 类似 wait() -> join + + // 关闭线程池 + executorService.shutdown(); + + } + + private static void echoThread() { + System.out.printf("当前线程[%s]正在执行...\n", Thread.currentThread().getName()); + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/src/main/java/com/segmentfault/deep/in/java/concurrency/CyclicBarrierDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/src/main/java/com/segmentfault/deep/in/java/concurrency/CyclicBarrierDemo.java" new file mode 100644 index 0000000..fbaf48a --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/src/main/java/com/segmentfault/deep/in/java/concurrency/CyclicBarrierDemo.java" @@ -0,0 +1,50 @@ +package com.segmentfault.deep.in.java.concurrency; + +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class CyclicBarrierDemo { + + public static void main(String[] args) throws BrokenBarrierException, InterruptedException { + + CyclicBarrier cb = new CyclicBarrier(4); + + ExecutorService executorService = Executors.newFixedThreadPool(3); + + for (int i = 0; i < 3; i++) { + executorService.submit(() -> { + try { + echoThread(); + cb.await(); // await() 让计数 -1 + } catch (Exception e) { + e.printStackTrace(); + } + }); + } + + Thread.sleep(5 * 100); + + // 当 count 数量等于 0,才会释放 + // 4 - 3 == 1 !=0 + // 再次 await() -1 => 4 - 3 - 1 = 0 + System.out.println(cb.getNumberWaiting()); + cb.await(); + System.out.println(cb.getNumberWaiting()); + +// // reset() 操作是恢复计数 0 -> 4 + cb.reset(); + System.out.println(cb.getNumberWaiting()); +// + // 关闭线程池 + executorService.shutdown(); + + } + + + private static void echoThread() { + System.out.printf("当前线程[%s]正在执行...\n", Thread.currentThread().getName()); + } + +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/src/main/java/com/segmentfault/deep/in/java/concurrency/ReentrantLockDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/src/main/java/com/segmentfault/deep/in/java/concurrency/ReentrantLockDemo.java" new file mode 100644 index 0000000..dcf2593 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/src/main/java/com/segmentfault/deep/in/java/concurrency/ReentrantLockDemo.java" @@ -0,0 +1,81 @@ +package com.segmentfault.deep.in.java.concurrency; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +public class ReentrantLockDemo { + + public static void main(String[] args) { + lockOpsMethods(); + } + + private static void lockOpsMethods() { + ReentrantLock lock = new ReentrantLock(); + int count = lock.getHoldCount(); + System.out.printf("在 lock() 方法调用之前的线程[%s]重进入数:%d\n", Thread.currentThread().getName(), count); + lock(lock, 100); + } + + private static void lock(ReentrantLock lock, int times) { + + if (times < 1) { + return; + } + + lock.lock(); + + try { + // times-- load, minus 1 + lock(lock, --times); + System.out.printf("第%s次在 lock() 方法调用之后的线程[%s]重进入数:%d\n", + times+1, + Thread.currentThread().getName(), + lock.getHoldCount()); + } finally { + lock.unlock(); + } + + } + + private static void conditionObject() { + Lock lock = new ReentrantLock(); + // 条件变量包括条件,同时它又是线程通讯媒介 + Condition condition = lock.newCondition(); + try { + condition.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + private static void tryLockInTimeout() { + Lock lock = new ReentrantLock(); + + try { + if (lock.tryLock(3, TimeUnit.SECONDS)) { // 当前仅当在规定的时间内获得锁 + // Lock API 语义补充了 synchronized 原语的不足 + // TODO Add some logic + } + } catch (InterruptedException e) { + // 重置中止状态(防止被中途清除 interrupt 状态) + Thread.currentThread().interrupt(); + // logger error message + } + } + + private static void synchronizedStatement() { + // 假设出现死锁或者饥饿 + synchronized (ReentrantLockDemo.class) { + + if (3 > 2) { // 条件 + try { + ReentrantLockDemo.class.wait(); // Object 线程通讯方法 + } catch (InterruptedException e) { + // logger error message + } + } + } + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/src/main/java/com/segmentfault/deep/in/java/concurrency/ReentrantReadWriteLockDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/src/main/java/com/segmentfault/deep/in/java/concurrency/ReentrantReadWriteLockDemo.java" new file mode 100644 index 0000000..921d0b0 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/src/main/java/com/segmentfault/deep/in/java/concurrency/ReentrantReadWriteLockDemo.java" @@ -0,0 +1,18 @@ +package com.segmentfault.deep.in.java.concurrency; + +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +public class ReentrantReadWriteLockDemo { + + public static void main(String[] args) { + + ReadWriteLock lock = new ReentrantReadWriteLock(); + + Lock readLock = lock.readLock(); + + Lock writeLock = lock.writeLock(); + + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/src/main/java/com/segmentfault/deep/in/java/concurrency/SemaphoreDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/src/main/java/com/segmentfault/deep/in/java/concurrency/SemaphoreDemo.java" new file mode 100644 index 0000000..0651054 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/src/main/java/com/segmentfault/deep/in/java/concurrency/SemaphoreDemo.java" @@ -0,0 +1,40 @@ +package com.segmentfault.deep.in.java.concurrency; + +import java.util.concurrent.*; + +public class SemaphoreDemo { + + public static void main(String[] args) throws BrokenBarrierException, InterruptedException { + + Semaphore cb = new Semaphore(4); + + ExecutorService executorService = Executors.newFixedThreadPool(3); + + for (int i = 0; i < 3; i++) { + executorService.submit(() -> { + try { + echoThread(); + cb.acquire(); // await() 让计数 -1 + } catch (Exception e) { + e.printStackTrace(); + } + }); + } + + Thread.sleep(5 * 100); + + // 当 count 数量等于 0,才会释放 + // 4 - 3 == 1 !=0 + // 再次 await() -1 => 4 - 3 - 1 = 0 +// + // 关闭线程池 + executorService.shutdown(); + + } + + + private static void echoThread() { + System.out.printf("当前线程[%s]正在执行...\n", Thread.currentThread().getName()); + } + +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/src/main/java/com/segmentfault/deep/in/java/concurrency/StampedLockDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/src/main/java/com/segmentfault/deep/in/java/concurrency/StampedLockDemo.java" new file mode 100644 index 0000000..26d7148 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-3/src/main/java/com/segmentfault/deep/in/java/concurrency/StampedLockDemo.java" @@ -0,0 +1,21 @@ +package com.segmentfault.deep.in.java.concurrency; + +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.StampedLock; + +public class StampedLockDemo { + + public static void main(String[] args) { + // Java 1.8 之后提供 + StampedLock lock = new StampedLock(); + long stamp = lock.tryOptimisticRead(); + Lock readLock = lock.asReadLock(); + try { + readLock.lock(); + + lock.validate(stamp); + } finally { + readLock.unlock(); + } + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/pom.xml" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/pom.xml" new file mode 100644 index 0000000..f4cef6e --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/pom.xml" @@ -0,0 +1,15 @@ + + + + stage-3 + com.segmentfault + 1.0-SNAPSHOT + + 4.0.0 + + stage-3-lesson-4 + 「一入 Java 深似海 」系列 :: 第三期 :: 第四节 + https://segmentfault.com/ls/1650000018320970/l/1500000018320681 + \ No newline at end of file diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/ArrayBlockingQueueConcurrentDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/ArrayBlockingQueueConcurrentDemo.java" new file mode 100644 index 0000000..7f04cbc --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/ArrayBlockingQueueConcurrentDemo.java" @@ -0,0 +1,43 @@ +package com.segmentfault.deep.in.java.concurrency; + +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; + +public class ArrayBlockingQueueConcurrentDemo { + + public static void main(String[] args) throws InterruptedException { + + // 最大允许添加 2 个元素 + BlockingQueue queue = new ArrayBlockingQueue<>(2, true); + // 申请 2 个大小的线程池 + ExecutorService executorService = Executors.newFixedThreadPool(2); + + for (AtomicInteger i = new AtomicInteger(1); i.get() < 100; i.incrementAndGet()) { + executorService.submit(() -> { // 写线程(1) + try { + queue.put(i.get()); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }); + + executorService.submit(() -> { // 读线程(1) + try { + System.out.println(queue.take()); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }); + } + +// executorService.submit(() -> { // 写线程(2) +// queue.put(2); +// }); + + + executorService.awaitTermination(10, TimeUnit.SECONDS); + // 关闭线程池 + executorService.shutdown(); + + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/ArrayBlockingQueueDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/ArrayBlockingQueueDemo.java" new file mode 100644 index 0000000..158b04d --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/ArrayBlockingQueueDemo.java" @@ -0,0 +1,46 @@ +package com.segmentfault.deep.in.java.concurrency; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; + +public class ArrayBlockingQueueDemo { + + public static void main(String[] args) throws InterruptedException { + + // ArrayBlockingQueue 是有限队列 + ArrayBlockingQueue queue = new ArrayBlockingQueue(3); + + // Queue 添加操作中 offer 安全性高于 add 方法 +// demoOfferMethod(queue); +// demoAddMethod(queue); + + demoPutMethod(queue); + // BlockingQueue 要使用 put 方法多于 offer 方法 + + System.out.println(queue); + } + + private static void demoPutMethod(BlockingQueue queue) throws InterruptedException { + queue.put(1); + queue.put(2); + queue.put(3); + // 如果超过了 capacity,? + queue.put(4); + } + + private static void demoAddMethod(BlockingQueue queue) { + queue.add(1); + queue.add(2); + queue.add(3); + // 如果超过了 capacity,throw new IllegalStateException("Queue full") +// queue.add(4); + } + + private static void demoOfferMethod(BlockingQueue queue) { + queue.offer(1); + queue.offer(2); + queue.offer(3); + // 如果超过了 capacity,后面的offer 会被忽略 + queue.offer(4); + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/CompletableFutureDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/CompletableFutureDemo.java" new file mode 100644 index 0000000..3904c5d --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/CompletableFutureDemo.java" @@ -0,0 +1,17 @@ +package com.segmentfault.deep.in.java.concurrency; + +import java.util.concurrent.CompletableFuture; + +public class CompletableFutureDemo { + + public static void main(String[] args) { + // CompletableFuture + + CompletableFuture.supplyAsync(() -> { + return 1; + }).thenApply(String::valueOf) + // 异常的方式结束 + .completeExceptionally(new RuntimeException()) + ; + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/ConcurrentHashMapDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/ConcurrentHashMapDemo.java" new file mode 100644 index 0000000..cd11224 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/ConcurrentHashMapDemo.java" @@ -0,0 +1,22 @@ +package com.segmentfault.deep.in.java.concurrency; + +public class ConcurrentHashMapDemo { + + public static void main(String[] args) { + + // ConcurrentHashMap 读多写少场景 + // 1.6 读(部分锁) -> 1.7 无锁(Segment) -> 1.8 无锁(红黑树——更好地解决 Hash 冲突) + // ConcurrentSkipListMap 读多写多场景(如果内存足够时) + + // ConcurrentHashMap + // table 2^n -> + // n = 1 -> size = 2 + // n = 2 -> size = 2^2 = 4 + // n = 3 -> size = 2^3 = 8 TREEIFY_THRESHOLD + // log2(8) = 3 + // [0] -> [1] -> [2] + // [0] -> [1] + // -> [2] + // n = 4 -> size = 2^4 = 16 + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/CopyOnWriteArrayListDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/CopyOnWriteArrayListDemo.java" new file mode 100644 index 0000000..4f00616 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/CopyOnWriteArrayListDemo.java" @@ -0,0 +1,31 @@ +package com.segmentfault.deep.in.java.concurrency; + +import java.util.Iterator; +import java.util.concurrent.CopyOnWriteArrayList; + +public class CopyOnWriteArrayListDemo { + + public static void main(String[] args) { + CopyOnWriteArrayList list = new CopyOnWriteArrayList<>(); // Diamond 语法 + + // main 线程插入三条数据 + // 安装 Thread ID + list.add(1); + // 判断当前线程 ID == main.threadId + list.add(2); + list.add(3); + // Copy + // JDK 升级两大核心性能提升 + // 1. 数组 + // 2. String + + // ConcurrentModificationException + int times = 0; + Iterator iterator = list.iterator(); + while (iterator.hasNext() && times < 100) { + iterator.next(); + list.add(2); + times++; + } + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/HashMapDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/HashMapDemo.java" new file mode 100644 index 0000000..bf748b7 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/HashMapDemo.java" @@ -0,0 +1,19 @@ +package com.segmentfault.deep.in.java.concurrency; + +import java.util.HashMap; +import java.util.Map; + +public class HashMapDemo { + + public static void main(String[] args) { + + String strValue = "Hello,World"; + + Integer intValue = new Integer(strValue.hashCode()); + + Map map = new HashMap<>(); + + map.put(strValue, 1); + map.put(intValue, 2); + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/Java9FlowDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/Java9FlowDemo.java" new file mode 100644 index 0000000..b5f9373 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/Java9FlowDemo.java" @@ -0,0 +1,72 @@ +package com.segmentfault.deep.in.java.concurrency; + +import java.util.concurrent.*; + +public class Java9FlowDemo { + + public static void main(String[] args) throws InterruptedException { + + // Java 7 try-catch 语法 + + try (SubmissionPublisher publisher = new SubmissionPublisher<>()) { + + // 订阅 + publisher.subscribe(new Flow.Subscriber() { + + private Flow.Subscription subscription; + + @Override + public void onSubscribe(Flow.Subscription subscription) { + this.subscription = subscription; + println("已订阅"); + // 订阅无限(Long.MAX_VALUE)数据 + subscription.request(Long.MAX_VALUE); + } + + @Override + public void onNext(String item) { + if ("exit".equalsIgnoreCase(item)) { + // 取消订阅 + subscription.cancel(); + return; + } else if ("exception".equalsIgnoreCase(item)) { + throw new RuntimeException("Throw an exception..."); + } + println("得到数据:" + item); + } + + @Override + public void onError(Throwable throwable) { + println("得到异常:" + throwable); + } + + @Override + public void onComplete() { + println("操作完成"); + } + }); + + // 发布者发布数据 + publisher.submit("Hello,World"); + publisher.submit("2019"); + + // 故意抛出异常 + publisher.submit("exception"); + + // exit 是退出命令 + publisher.submit("exit"); + // 当 exit 出现时,忽略后续提交 + publisher.submit("ABCDEFG"); + publisher.submit("HIGKLMN"); + + ExecutorService executor = (ExecutorService) publisher.getExecutor(); + + executor.awaitTermination(100, TimeUnit.MILLISECONDS); + + } + } + + private static void println(Object object) { + System.out.printf("[线程: %s] - %s\n", Thread.currentThread().getName(), object); + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/LinkedBlockingQueueConcurrentDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/LinkedBlockingQueueConcurrentDemo.java" new file mode 100644 index 0000000..dc284b5 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/LinkedBlockingQueueConcurrentDemo.java" @@ -0,0 +1,43 @@ +package com.segmentfault.deep.in.java.concurrency; + +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; + +public class LinkedBlockingQueueConcurrentDemo { + + public static void main(String[] args) throws InterruptedException { + + // 最大允许添加 2 个元素 + BlockingQueue queue = new LinkedBlockingQueue<>(2); + // 申请 2 个大小的线程池 + ExecutorService executorService = Executors.newFixedThreadPool(2); + + for (AtomicInteger i = new AtomicInteger(1); i.get() < 100; i.incrementAndGet()) { + executorService.submit(() -> { // 写线程(1) + try { + queue.put(i.get()); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }); + + executorService.submit(() -> { // 读线程(1) + try { + System.out.println(queue.take()); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }); + } + +// executorService.submit(() -> { // 写线程(2) +// queue.put(2); +// }); + + + executorService.awaitTermination(10, TimeUnit.SECONDS); + // 关闭线程池 + executorService.shutdown(); + + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/MapEntryDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/MapEntryDemo.java" new file mode 100644 index 0000000..cac5f24 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/MapEntryDemo.java" @@ -0,0 +1,51 @@ +package com.segmentfault.deep.in.java.concurrency; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentSkipListMap; + +public class MapEntryDemo { + + public static void main(String[] args) { + Map map = new HashMap<>(); + map.put("A", 1); + map.put("B", 2); + map.put("C", 3); + demoMap(map); + + System.out.println(map); + + //注意:Java Concurrent Map 可能未实现 Map.Entry#setValue(Object) 方法 + Map skipListMap = new ConcurrentSkipListMap<>(); + + skipListMap.put("A", 1); + skipListMap.put("B", 2); + skipListMap.put("C", 3); + + demoMap(skipListMap); + + System.out.println(skipListMap); + } + + private static void demoMap(Map map) { + + // 问题:如何让所有的成员值 +1 + for (Map.Entry entry : map.entrySet()) { + slowApproach(entry, map); + fastApproach(entry); + } + } + + private static void fastApproach(Map.Entry entry) { + entry.setValue(entry.getValue() + 1); + } + + private static void slowApproach(Map.Entry entry, Map map) { + String key = entry.getKey(); + Integer value = entry.getValue(); + // Key 的计算消耗时间 + // +1 + value += 1; + map.put(key, value); + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/QuickSortForkJoinDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/QuickSortForkJoinDemo.java" new file mode 100644 index 0000000..5f9a124 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/QuickSortForkJoinDemo.java" @@ -0,0 +1,104 @@ +package com.segmentfault.deep.in.java.concurrency; + +import java.util.Arrays; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.RecursiveAction; +import java.util.concurrent.TimeUnit; + +public class QuickSortForkJoinDemo { + + public static void main(String[] args) throws InterruptedException { + + Integer[] values = new Integer[]{2, 5, 6, 7, 8, 8, 9, 2, 1, 6, 7, 5, 6, 11, 23}; + + ForkJoinPool pool = new ForkJoinPool(); + + pool.submit(new QuickSortTask(values)); + + pool.awaitTermination(100, TimeUnit.MILLISECONDS); + + pool.shutdown(); + + System.out.println(Arrays.asList(values)); + } + + private static class QuickSortTask extends RecursiveAction { + + private final Integer[] parts; + + private final int low; + + private final int high; + // 设置一个阈值 + private static final int THRESHOLD = 4; + + private QuickSortTask(Integer[] parts) { + this.parts = parts; + this.low = 0; + this.high = parts.length - 1; + } + + private QuickSortTask(Integer[] parts, int low, int high) { + this.parts = parts; + this.low = low; + this.high = high; + } + + @Override + protected void compute() { + if (high - low < THRESHOLD) { // 范围低于阈值时,直接排序 + sort(parts, low, high); + } else { + int pivot = partition(parts, low, high); + QuickSortTask task = new QuickSortTask(parts, low, pivot - 1); + QuickSortTask task2 = new QuickSortTask(parts, pivot + 1, high); + task.fork().join(); + task2.fork().join(); + } + } + + /** + * 获取分区索引 + * + * @param values 数组对象 + * @param low 低位索引 + * @param high 高位索引 + * @return 分区索引 + */ + int partition(Integer[] values, int low, int high) { + // 获取 pivot = values[high] + + // [3, 1, 2, 5, 4] + // pivot = 4 + // -1 + // [0] = 3 < 4 (0) + // [1] = 1 < 4 (1) + // [2] = 2 < 4 (2) + // [3] = 5 > 4 (3) + // => [(3, 1, 2), (4), (5)] + // pIndex = 3 + + Integer pivot = values[high]; + int i = low; + + for (int j = low; j < high; j++) { + if (values[j].compareTo(pivot) < 1) { // <= + Integer temp = values[i]; // 低位数据 + values[i] = values[j]; // 低位数据获取高位数据 + values[j] = temp; + i++; // -1 -> 0 + } + } + + Integer temp = values[i]; + values[i] = values[high]; + values[high] = temp; + + return i; + } + + private void sort(Integer[] parts, int low, int high) { + Arrays.sort(parts, low, high + 1); + } + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/SynchronousQueueDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/SynchronousQueueDemo.java" new file mode 100644 index 0000000..1728c3b --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-3/stage-3-lesson-4/src/main/java/com/segmentfault/deep/in/java/concurrency/SynchronousQueueDemo.java" @@ -0,0 +1,72 @@ +package com.segmentfault.deep.in.java.concurrency; + +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; + +public class SynchronousQueueDemo { + + public static void main(String[] args) throws InterruptedException { + + + // SynchronousQueue 互斥使用场景 + // SynchronousQueue put() 完成之后,必须被其他线程 take() + // capacity == 0 , 又允许插入(put) 一个元素 + // offer 方法无效,add 方法抛出异常 + BlockingQueue sQueue = new SynchronousQueue<>(true); + // 申请 2 个大小的线程池 + ExecutorService executorService = Executors.newFixedThreadPool(2); + + for (AtomicInteger i = new AtomicInteger(1); i.get() < 100; i.incrementAndGet()) { + executorService.execute(() -> { // 写线程 + try { + // 必须要有 put,不能用 offer + // BlockingQueue 尽可能用 put,避免使用 offer,最好不要用 add + // sQueue.offer(1); // 如果 SynchronousQueue 被其他线程调用 take() 方法的话,会发生死锁 + sQueue.put(i.get()); + } catch (Exception e) { + e.printStackTrace(); + } + }); + + executorService.execute(() -> { // 读线程 + try { + System.out.println(sQueue.take()); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }); + } + + executorService.awaitTermination(10, TimeUnit.MICROSECONDS); + + executorService.shutdown(); + } + + private static void synchronousQueuevsArrayBlockingQueue() throws InterruptedException { + // size == 0 特殊 ArrayBlockingQueue + BlockingQueue sQueue = new SynchronousQueue(); + sQueue.put(1); + + System.out.println(sQueue.size()); + + BlockingQueue aQueue = new ArrayBlockingQueue<>(1); + + aQueue.add(1); + + System.out.println(aQueue.size()); + + } + + // offer 方法来自于 Queue 接口,因此,子接口无法超越 Queue 方法签名 + + public boolean equals(Object object) +// throws Exception // 错误(编译时):超越父类 Object equals(Object) 方法签名 + throws RuntimeException // 非 checked 异常时没有以上限制 + { + + return false; + } +} + + + diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/pom.xml" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/pom.xml" new file mode 100644 index 0000000..e092352 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/pom.xml" @@ -0,0 +1,34 @@ + + + + deep-in-java + com.segmentfault + 1.0-SNAPSHOT + + 4.0.0 + + stage-4 + pom + 「一入 Java 深似海 」系列 :: 第四期 + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 11 + 11 + + + + + + stage-4-lesson-1 + stage-4-lesson-2 + stage-4-lesson-3 + + \ No newline at end of file diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-1/pom.xml" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-1/pom.xml" new file mode 100644 index 0000000..03659c0 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-1/pom.xml" @@ -0,0 +1,16 @@ + + + + stage-4 + com.segmentfault + 1.0-SNAPSHOT + + 4.0.0 + + stage-4-lesson-1 + 「一入 Java 深似海 」系列 :: 第四期 :: 第一节 + + + \ No newline at end of file diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-1/src/main/java/com/segmentfault/deep/in/java/concurrency/HelloWorldThreadDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-1/src/main/java/com/segmentfault/deep/in/java/concurrency/HelloWorldThreadDemo.java" new file mode 100644 index 0000000..6e19324 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-1/src/main/java/com/segmentfault/deep/in/java/concurrency/HelloWorldThreadDemo.java" @@ -0,0 +1,24 @@ +package com.segmentfault.deep.in.java.concurrency; + +public class HelloWorldThreadDemo { + + public static void main(String[] args) throws Exception { + + // 创建 Java 线程 + // Java 线程对象和 JVM OS 线程并不是同一对象 + Thread t1 = new Thread(HelloWorldThreadDemo::helloWorld); + // 主线程 main 显示地启动子线程 + t1.start(); // pthread_create() + + // 等待线程执行结束 + t1.join(); // pthread_join() + + // 当线程 isAlive() 返回 false 时,JVM 线程已经消亡了(delete this) + System.out.printf("线程状态 : %s , 是否存活 : %s", t1.getState(), t1.isAlive()); + } + + static void helloWorld() { + System.out.printf("Thread[id : %d] - Hello World\n", + Thread.currentThread().getId()); + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-1/src/main/java/com/segmentfault/deep/in/java/concurrency/SynchronizationDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-1/src/main/java/com/segmentfault/deep/in/java/concurrency/SynchronizationDemo.java" new file mode 100644 index 0000000..91cece8 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-1/src/main/java/com/segmentfault/deep/in/java/concurrency/SynchronizationDemo.java" @@ -0,0 +1,50 @@ +package com.segmentfault.deep.in.java.concurrency; + +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +public class SynchronizationDemo { + + // pthread_mutex_t lock; + static Lock lock = new ReentrantLock(); + + static volatile int counter = 0; + + public static void main(String[] args) throws Exception { + + // pthread_cond_t condition1; + Condition condition1 = lock.newCondition(); + + // 前提:Lock#lock() + // await() 和 signal() 或 signalAll() + + // 前提:synchronized(object) -> + // Object wait() 和 notify() 或 notifyAll(); + + synchronized (Object.class) { +// Object.class.wait(); + } + + Thread t1 = new Thread(SynchronizationDemo::addCounter); + Thread t2 = new Thread(SynchronizationDemo::addCounter); + t1.start(); + t2.start(); + + t1.join(); + t2.join(); + } + + private static void addCounter() { + lock.lock(); // pthread_mutex_lock() + // lock.tryLock() // pthread_mutex_trylock() + System.out.println(getThreadPrefix() + "Before Counter : " + counter); + counter++; + System.out.println(getThreadPrefix() + "After Counter : " + counter); + lock.unlock(); // pthread_mutex_unlock() + } + + private static String getThreadPrefix() { + return "Thread[" + Thread.currentThread().getId() + "] : "; + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-2/pom.xml" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-2/pom.xml" new file mode 100644 index 0000000..3d80846 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-2/pom.xml" @@ -0,0 +1,15 @@ + + + + stage-4 + com.segmentfault + 1.0-SNAPSHOT + + 4.0.0 + + stage-4-lesson-2 + 「一入 Java 深似海 」系列 :: 第四期 :: 第二节 + + \ No newline at end of file diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-2/src/main/java/com/segmentfault/deep/in/java/memory/model/HappensBeforeRelationshipDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-2/src/main/java/com/segmentfault/deep/in/java/memory/model/HappensBeforeRelationshipDemo.java" new file mode 100644 index 0000000..cc9d563 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-2/src/main/java/com/segmentfault/deep/in/java/memory/model/HappensBeforeRelationshipDemo.java" @@ -0,0 +1,80 @@ +package com.segmentfault.deep.in.java.memory.model; + +/** + * happens-before relationship + */ +public class HappensBeforeRelationshipDemo { + + // 性能开销:Lock > CAS > volatile + // 术语: Mutex > CAS > Memory Barrier + // 底层分析:N多指令 > 多个指令 > 单个或若干指令 + + public static void main(String[] args) { + + } + + /** + * If x and y are actions of the same thread and x comes before y in program order, + * then hb(x, y). + */ + private static void inSameThread() { + // action1 + // action2 + } + + /** + * There is a happens-before edge from the end of a constructor of an object to the + * start of a finalizer (§12.6) for that object + */ + private static void constructorHappensBeforeFinalizer() { + // 构造早于销毁(终结)之前 + // 构造对象是在用户线程(main、子线程)中执行 + // Finalizer 操作是 JVM 线程(GC 线程)中执行 + // 对象存放在 Heap 里面,Heap 对于线程是共享的 + // 假设 Object 刚创建,Finalizer 线程看到该对象,马上回收 + } + + /** + * lock 对象是一个锁对象,也可视作 monitor + */ + private static final Object monitor = new Object(); + + /** + * The wait methods of class Object (§17.2.1) have lock and unlock actions + * associated with them; their happens-before relationships are defined by these + * associated actions. + * + * @throws InterruptedException + */ + private static void synchronizedAndWait() throws InterruptedException { + + // JMM 描述: + // monitor (lock) happens-before monitor.wait() + // monitor.wait() happens-before monitor (unlock) + + // 实际情况: + // monitor (lock) synchronizes-with monitor.wait() + // monitor.wait() synchronizes-with monitor (unlock) + + // if x synchronizes-with y , then x happens-before y + synchronized (monitor) { + monitor.wait(); // + // 当 wait() 方法所属对象没有被 synchronized 关键字修饰, + // 将抛出 IllegalMonitorStateException + } + } + + private static void threadStartAndJoin() throws InterruptedException { + + Thread t = new Thread(() -> { + // action 动作 + }); + + t.start(); // start() 方法 happens-before actions 之前 + + // main 线程调用线程 t 的join() 方法 + // 在 join() 方法返回之前,t 所有的 actions 已执行结束 + t.join(); + + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-2/src/main/java/com/segmentfault/deep/in/java/memory/model/JavaMemoryModelDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-2/src/main/java/com/segmentfault/deep/in/java/memory/model/JavaMemoryModelDemo.java" new file mode 100644 index 0000000..7c9057c --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-2/src/main/java/com/segmentfault/deep/in/java/memory/model/JavaMemoryModelDemo.java" @@ -0,0 +1,40 @@ +package com.segmentfault.deep.in.java.memory.model; + +public class JavaMemoryModelDemo { + + /** + * 广义同步:狭义锁(互斥)、volatile 以及原子操作(Unsafe) + * Java9+ VarHandle + */ + + /** + * 狭义锁(互斥): + * OS 原语(Windows): + * HANDLE mutex = CreateMutex(NULL, FALSE, NULL); + * CRITICAL_SECTION critSec; + * POSIX Thread 等高级 API: + * pthread_mutex_t 数据结构 + */ + + /** + * volatile + * 确保: + * 变量的可见性 + * 引用的原子性:https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html + * 实现: + * 大部分利用 C++ volatile 编译时限制重排(内存屏障) + * Memory Barriers:https://www.infoq.com/articles/memory_barriers_jvm_concurrency + * 部分通过汇编实现 + * 源码快速路径:orderAccess.hpp + * + */ + + /** + * 原子操作(Atomic) + * 确保: + * 变量的原子操作(自增长、exchange、CAS 等操作) + * 实现: + * 利用汇编指令 + * 源码快速路径:atomic.hpp + */ +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-2/src/main/java/com/segmentfault/deep/in/java/memory/model/SynchronizedWithRelationDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-2/src/main/java/com/segmentfault/deep/in/java/memory/model/SynchronizedWithRelationDemo.java" new file mode 100644 index 0000000..21d116a --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-2/src/main/java/com/segmentfault/deep/in/java/memory/model/SynchronizedWithRelationDemo.java" @@ -0,0 +1,162 @@ +package com.segmentfault.deep.in.java.memory.model; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +/** + * synchronized-with Relation + */ +public class SynchronizedWithRelationDemo { + + private static final Object lock = new Object(); + + public static void main(String[] args) { + + } + + private static volatile int sharedData; + + /** + * An unlock action on monitor m synchronizes-with all subsequent lock actions on + * m (where "subsequent" is defined according to the synchronization order) + * + * @param data + */ + private static void synchronizedChangeData(int data) { + // T1 和 T2 两个线程 + // T1 先获得锁 + // T1 lock -> run() -> unlock + // T2 被停顿(park) + // T3 进入(停顿) + // T1 unlock + // T2 或 T3 获得锁机会 + // T3 获得锁(T2 被停顿) + // T3 lock -> unlock + // 结果 + // T1 unlock -> T3 lock + synchronized (lock) { + sharedData = data; + } // unlock the monitor(lock) + } + + + /** + * A write to a volatile variable v (§8.3.1.4) synchronizes-with all subsequent + * reads of v by any thread (where "subsequent" is defined according to the + * synchronization order) + *

+ * 假设 + * T(w) :写线程 + * T(r) : 读线程 + * 且 T(w) 1 -> sharedData volatile 写 -> 0 => 1 + * T(r) 1...n -> sharedData volatile 读 -> 0 => 1 + */ + private static int getSharedData() { + // volatile 读 + // sharedData(1) + return sharedData; + } + + private static void volatileChangeDate(int data) { + // volatile 写 + // sharedData(0) -> 1 + sharedData = data; + + // volatile 读 + int tmpData = sharedData; + } + + /** + * An action that starts a thread synchronizes-with the first action in the thread it + * starts. + */ + private static void threadStart() { + Thread thread = new Thread(() -> { + }); + + thread.start(); // Thread.start() 方法必然在 Thread.run() 方法之前执行 + } + + private static class Person { + + private final String name; + + private final int age; + + private final Collection tags; + +// public Person() { +// // name = null +// // age = 0 +// } + + /** + * 线程在读取 Person 对象属性(name 或 age)时,线程不会读到字段在初始化的中间状态 + * + * @param name + * @param age + * @param tags + */ + public Person(String name, int age, Collection tags) { + this.name = name; // String 是不变对象(引用) + this.age = age; // age 是原生类型(复制) + this.tags = tags; // Collection 是可变对象(引用) + } + + } + + + private static void initializeProperties() { + + /** + * Person 对象初始化完成后,才能被其他线程访问对象属性 + */ + List tags = Arrays.asList("A", "B", "C"); + /** + * Java 方法参数特点 + * 对于对象类型,引用 + * 引用:普通对象、数组、集合(Collection、Map) + * 对于原生类型,复制 + */ + Person person = new Person("小马哥", 33, tags); + + /** + * 修改第三个元素 "C" -> "E" + */ + tags.set(2, "E"); + + Thread thread = new Thread(() -> { + person.toString(); + }); + } + + + private volatile boolean interrupted = false; + + private static void threadInterrupt() { + + Thread t2 = new Thread(() -> { + if (Thread.interrupted()) { // volatile 读 t2 interrupt true and is cleared. + // 会被执行 + } + }); + + Thread t1 = new Thread(() -> { + // T1 调用 T2 interrupt() 方法 + t2.interrupt(); // volatile 写 + // t2 interrupt 状态 false -> true + }); + + + Thread t3 = new Thread(() -> { + if (t2.isInterrupted()) { // volatile 读 t2 interrupt true + // 会被执行 + } + }); + + // volatile 写 -> volatile 读 + // t1 -> interrupt t2 -> t3,t4,t4 read isInterrupted() == true + + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-3/pom.xml" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-3/pom.xml" new file mode 100644 index 0000000..89fb545 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-3/pom.xml" @@ -0,0 +1,15 @@ + + + + stage-4 + com.segmentfault + 1.0-SNAPSHOT + + 4.0.0 + + stage-4-lesson-3 + 「一入 Java 深似海 」系列 :: 第四期 :: 第三节 + + \ No newline at end of file diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-3/src/main/java/com/segmentfault/deep/in/java/aqs/AbstractQueuedSynchronizerDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-3/src/main/java/com/segmentfault/deep/in/java/aqs/AbstractQueuedSynchronizerDemo.java" new file mode 100644 index 0000000..3a27d99 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-4/stage-4-lesson-3/src/main/java/com/segmentfault/deep/in/java/aqs/AbstractQueuedSynchronizerDemo.java" @@ -0,0 +1,78 @@ +package com.segmentfault.deep.in.java.aqs; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +public class AbstractQueuedSynchronizerDemo { + + // ReentrantLock is AbstractQueuedSynchronizer + private static Lock lock = new ReentrantLock(); + + // Condition is a part of ReentrantLock or AbstractQueuedSynchronizer + private static Condition condition = lock.newCondition(); + + public static void main(String[] args) throws InterruptedException { + + ExecutorService executorService = Executors.newFixedThreadPool(3); + + // 一个线程获得锁,另外一个线程入队 + + // main -> thread-2.interrupt() + // sub-threads + List threads = new ArrayList<>(); + + executorService.submit(() -> { + threads.add(Thread.currentThread()); + action(); + + }); // thread-1 + executorService.submit(AbstractQueuedSynchronizerDemo::action); // thread-1 + executorService.submit(AbstractQueuedSynchronizerDemo::action); // thread-2 + executorService.submit(AbstractQueuedSynchronizerDemo::action); // thread-3 + + + // 非公平锁 + // thread-1 unlock -> release -> unpark thread-2 -> thread-2 try acquire + // thread-4 or thread-5 lock -> try acquire + + // PS : unpark = LockSupport.unpark + + // 公平锁 + // thread-1 unlock -> release -> unpark thread-2 -> thread-2 try acquire + // thread-2 lock -> .. + // thread-3 wait + // thread-4 wait + // thread-5 wait + + // 等待 200 秒 + executorService.awaitTermination(200, TimeUnit.SECONDS); + // 关闭线程池 + executorService.shutdown(); + + } + + private static void action() { + System.out.printf("当前线程[%s] 正在等待您的输入\n", Thread.currentThread().getName()); + // I/O 中断线程 + try { + + + // 利用 ReentrantLock 作为 AQS 实现,理解内部数据结构 + lock.lock(); + System.in.read(); + System.out.printf("当前线程[%s] 执行结束...\n", Thread.currentThread().getName()); + } catch (IOException e) { + throw new RuntimeException(); + } finally { + lock.unlock(); + } + } + +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-5/pom.xml" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-5/pom.xml" new file mode 100644 index 0000000..5354e13 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-5/pom.xml" @@ -0,0 +1,19 @@ + + + + deep-in-java + com.segmentfault + 1.0-SNAPSHOT + + 4.0.0 + + stage-5 + pom + 「一入 Java 深似海 」系列 :: 第五期 + + stage-5-lesson-1 + + + \ No newline at end of file diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-5/stage-5-lesson-1/pom.xml" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-5/stage-5-lesson-1/pom.xml" new file mode 100644 index 0000000..fff295f --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-5/stage-5-lesson-1/pom.xml" @@ -0,0 +1,26 @@ + + + + stage-5 + com.segmentfault + 1.0-SNAPSHOT + + 4.0.0 + + stage-5-lesson-1 + 「一入 Java 深似海 」系列 :: 第五期 :: 第一节 + + + + + + commons-io + commons-io + 2.6 + + + + + \ No newline at end of file diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-5/stage-5-lesson-1/src/main/java/com/segmentfault/deep/in/java/ClassAndClassLoaderDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-5/stage-5-lesson-1/src/main/java/com/segmentfault/deep/in/java/ClassAndClassLoaderDemo.java" new file mode 100644 index 0000000..57354fd --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-5/stage-5-lesson-1/src/main/java/com/segmentfault/deep/in/java/ClassAndClassLoaderDemo.java" @@ -0,0 +1,30 @@ +package com.segmentfault.deep.in.java; + +/** + * Class 与 ClassLoader 之间的关系 + */ +public class ClassAndClassLoaderDemo { + + public static void main(String[] args) { + + // 获取加载 Object.class 的 ClassLoader + // Object 是被 Bootstrap ClassLoader 加载,其 Java 表现形式为 null + getClassLoader(Object.class); + // 获取加载原生类型 int 的 ClassLoader + // int.class 是被 Bootstrap ClassLoader 加载,其 Java 表现形式为 null + getClassLoader(int.class); + + // 当前 ClassAndClassLoaderDemo? + getClassLoader(ClassAndClassLoaderDemo.class); + // 加载 ClassAndClassLoaderDemo.class 的 ClassLoader + // 是否与系统 ClassLoader 相同 + System.out.println(ClassAndClassLoaderDemo.class.getClassLoader() + == ClassLoader.getSystemClassLoader()); + + } + + private static void getClassLoader(Class klass) { + System.out.printf("当前类[%s] 被 %s ClassLoader 加载\n", klass, + klass.getClassLoader()); + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-5/stage-5-lesson-1/src/main/java/com/segmentfault/deep/in/java/ClassLoaderAndClassPathDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-5/stage-5-lesson-1/src/main/java/com/segmentfault/deep/in/java/ClassLoaderAndClassPathDemo.java" new file mode 100644 index 0000000..0aa974d --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-5/stage-5-lesson-1/src/main/java/com/segmentfault/deep/in/java/ClassLoaderAndClassPathDemo.java" @@ -0,0 +1,30 @@ +package com.segmentfault.deep.in.java; + +/** + * ClassLoader 与 ClassPath 之间的关系示例代码 + */ +public class ClassLoaderAndClassPathDemo { + + + public static void main(String[] args) { + // 通常,在 JVM 进程中添加 -verbose:class 参数来显示加载的 Class + // 所在的位置(source),如: + // [0.397s][info][class,load] com.segmentfault.deep.in.java.ClassLoaderAndClassPathDemo source: file:/E:/workspace/github/mercyblitz/segmentfault-lessons/%e3%80%8c%e4%b8%80%e5%85%a5%20Java%20%e6%b7%b1%e4%bc%bc%e6%b5%b7%20%e3%80%8d/%e4%bb%a3%e7%a0%81/segmentfault/deep-in-java/stage-5/stage-5-lesson-1/target/classes/ + // Bootstrap ClassLoader 加载的 Class 将会抛出 java.lang.NullPointerException +// getClassLocation(Object.class); +// getClassLocation(int.class); + // 类资源与 URL 有关联,是否意味着 ClassLoader 与 URL 存在关联 + getClassLocation(ClassLoaderAndClassPathDemo.class); + // Spring Boot spring-boot-loader + // 文件目录:Expose -> File Handler + // 文件:JAR、WAR、EAR Jar Handler + // URL 抽象 Java 资源管理 + + + } + + private static void getClassLocation(Class klass) { + System.out.printf("类[%s] 资源所在的位置:%s\n", klass, + klass.getProtectionDomain().getCodeSource().getLocation()); + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-5/stage-5-lesson-1/src/main/java/com/segmentfault/deep/in/java/ClassLoaderDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-5/stage-5-lesson-1/src/main/java/com/segmentfault/deep/in/java/ClassLoaderDemo.java" new file mode 100644 index 0000000..468b6ef --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-5/stage-5-lesson-1/src/main/java/com/segmentfault/deep/in/java/ClassLoaderDemo.java" @@ -0,0 +1,67 @@ +package com.segmentfault.deep.in.java; + +import java.util.ServiceLoader; + +/** + * ClassLoader 示例代码 + */ +public class ClassLoaderDemo { + + public static void main(String[] args) { + // 系统 ClassLoader + // Java 8 结果:sun.misc.Launcher$AppClassLoader@18b4aac2 + // Java 12 结果:jdk.internal.loader.ClassLoaders$AppClassLoader@3fee733d + System.out.println(ClassLoader.getSystemClassLoader()); // 只读 + // 应用 ClassLoader + // Java 8 结果:sun.misc.Launcher$AppClassLoader@18b4aac2 + // Java 12 结果:jdk.internal.loader.ClassLoaders$AppClassLoader@3fee733d + System.out.println(Thread.currentThread().getContextClassLoader()); // 可修改 + + // 如何实现类隔离,通过修改 Thread 上下文 ClassLoader + + + // ClassLoader previousClassLoader = Thread.currentThread().getContextLoader(); + // previousClassLoader 能够加载 User.class V1 版本(user-api-1.0.0.jar 文件中,在 /classpath1 目录下) + // User.class V2 版本 (user-api-2.0.0.jar 文件中,在 /classpath2 目录下) + // loadUser 操作加载 User.class V2 版本 + + // previousClassLoader ClassPath -> /classpath1 + // newClassLoader ClassPath -> /classpath2 + + // 通常,系统或者应用(包括自定义) ClassLoader 均为 URLClassLoader 子类 + } + + private static void changeClassLoader(ClassLoader newClassLoader) { + Thread currentThread = Thread.currentThread(); + // 当前 ClassLoader 无法加载 User.class 类,不过该类能被 newClassLoader 加载 + ClassLoader previousClassLoader = currentThread.getContextClassLoader(); + try { + currentThread.setContextClassLoader(newClassLoader); // 需要 setContextClassLoader 安全权限 + // 利用新的 ClassLoader 来加载类 + } catch (SecurityException e) { + + } finally { + currentThread.setContextClassLoader(previousClassLoader); + } + } + + private static void loadUser() { // 兼容或适配老的 ClassLoader 代码 + // JAXB 通过线程上下文 ClassLoader 切换不同实现 SPI + // JAXB 1.x 2.x + // JDK 提供的 API 1.x + // 第三方包实现 2.x + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + try { + classLoader.loadClass("User"); // 使用 V2 + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } +} + +//class User { // V1 +// +//} + +// Class User { // V2 +// } diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-5/stage-5-lesson-1/src/main/java/com/segmentfault/deep/in/java/ClassLoadingDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-5/stage-5-lesson-1/src/main/java/com/segmentfault/deep/in/java/ClassLoadingDemo.java" new file mode 100644 index 0000000..787f4af --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-5/stage-5-lesson-1/src/main/java/com/segmentfault/deep/in/java/ClassLoadingDemo.java" @@ -0,0 +1,93 @@ +package com.segmentfault.deep.in.java; + +import org.apache.commons.io.FileUtils; + +import java.io.File; +import java.io.IOException; +import java.util.stream.Stream; + +/** + * 类加载过程 + */ +public class ClassLoadingDemo { + + public static void main(String[] args) throws ClassNotFoundException { + + // 当前 main 线程 ClassLoader + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + // 加载某个 Class 对象 + // User user = ... -> load class + + // 当前工程相对路径:stage-5/stage-5-lesson-1 + // 当前工程绝对路径:${user.dir}/stage-5/stage-5-lesson-1 + // 当前工程ClassPath :${user.dir}/stage-5/stage-5-lesson-1/target/classes + // User 类全名:com.segmentfault.deep.in.java.User + // User.class 文件路径:${ClassPath}/com/segmentfault/deep/in/java/User.class + + String className = "com.segmentfault.deep.in.java.User"; + // com/segmentfault/deep/in/java/User.class + String classFileName = className.replace('.', '/').concat(".class"); + String classPath = System.getProperty("user.dir") + "/stage-5/stage-5-lesson-1/target/classes"; + // User.class 类文件的绝对路径 + File classFile = new File(classPath, classFileName); + + // ClassLoader 也是对象,也会被 GC 管理 + MyClassLoader myClassLoader = new MyClassLoader(); + // .class 文件变为字节流 byte[],再定义 Class 对象 + Class userClass = myClassLoader.defineClass(className, classFile); + + System.out.println("当前类对象:" + userClass); + Stream.of(userClass.getDeclaredFields()) + .forEach(field -> { + System.out.println("当前字段信息:" + field); + }); + + Class userClassFromThreadContextClassLoader = classLoader.loadClass(className); + // User.class 被 MyClassLoader 加载后,是否与线程上下文加载的 User.class 对象是否一致? + // 这个现象能够解释 Spring spring-boot-devtools 模块 Class!=Class 问题 + System.out.println("userClass == userClassFromThreadContextClassLoader ? " + + (userClass == userClassFromThreadContextClassLoader)); + + // 重新替换掉线程上下文 ClassLoader + // myClassLoader -> Thread.currentThread().getContextClassLoader() + Thread.currentThread().setContextClassLoader(myClassLoader); + // 老的线程上下文 ClassLoader 是 MyClassLoader 的 parent,由于双亲委派,及时是 MyClassLoader 重新调用 + // loadClass(String) 方法,也不会重新加载 + Class userClassFromMyClassLoader = classLoader.loadClass(className); + System.out.println("userClass == userClassFromMyClassLoader ? " + + (userClass == userClassFromMyClassLoader)); + + // 已加载 Class 是如何实现,目标方法: java.lang.ClassLoader.findLoadedClass0 + System.out.println( + "userClassFromThreadContextClassLoader == userClassFromMyClassLoader ? " + + (userClassFromThreadContextClassLoader == userClassFromMyClassLoader)); + } + + static class MyClassLoader extends ClassLoader { + + public MyClassLoader() { + // 当前线程上下文 ClassLoader 作为 Parent + super(Thread.currentThread().getContextClassLoader()); + } + + // 文件 -> 定义某个 Class + public Class defineClass(String name, File classFile) { + // File classFile -> byte[] + byte[] bytes = loadBytes(classFile); + // 利用 ClassLoader defineClass 方法来定义 Class + // 可用于动态加载 + return super.defineClass(name, bytes, 0, bytes.length); + + } + + private byte[] loadBytes(File classFile) { + byte[] bytes = null; + try { + bytes = FileUtils.readFileToByteArray(classFile); + } catch (IOException e) { + throw new RuntimeException(e); + } + return bytes; + } + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-5/stage-5-lesson-1/src/main/java/com/segmentfault/deep/in/java/ClassObjectDemo.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-5/stage-5-lesson-1/src/main/java/com/segmentfault/deep/in/java/ClassObjectDemo.java" new file mode 100644 index 0000000..e1590b0 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-5/stage-5-lesson-1/src/main/java/com/segmentfault/deep/in/java/ClassObjectDemo.java" @@ -0,0 +1,33 @@ +package com.segmentfault.deep.in.java; + +/** + * 类对象示例代码 + */ +public class ClassObjectDemo { + + public static void main(String[] args) { + + // ClassLoader 在加载类过程(验证)中,去重操作 + // 验证:运行时校验 .class 文件(已经编译结果) + // .class 文件版版本 Java 5 泛型,JVM 版本过低版本不兼容 + // 处理:参考《深入 Java 虚拟机》第二版 + // 双亲委派(类加载以及类存储) + Class objectClass = Object.class; + + // ClassLoader + + // 原生类型也有类对象 + Class intClass = int.class; + + isPrimitive(objectClass); + isPrimitive(intClass); + + // Object.class 和 int.class 均被 Bootstrap ClassLoader + // Bootstrap ClassLoader 在 Java 9 之前,就是 rt.jar + // 除 Bootstrap ClassLoader 之外,System ClassLoader, Application ClassLoader + } + + private static void isPrimitive(Class klass) { + System.out.printf("类[%s] 是否属于原生类型:%s\n", klass.getName(), klass.isPrimitive()); + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-5/stage-5-lesson-1/src/main/java/com/segmentfault/deep/in/java/User.java" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-5/stage-5-lesson-1/src/main/java/com/segmentfault/deep/in/java/User.java" new file mode 100644 index 0000000..1a1a8bb --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/deep-in-java/stage-5/stage-5-lesson-1/src/main/java/com/segmentfault/deep/in/java/User.java" @@ -0,0 +1,17 @@ +package com.segmentfault.deep.in.java; + +/** + * V1 版本拥有 ID 字段 + */ +public class User { + + private long id; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } +} diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Attributes/PosixThread_Attributes.sln" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Attributes/PosixThread_Attributes.sln" new file mode 100644 index 0000000..40f1d52 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Attributes/PosixThread_Attributes.sln" @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.438 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PosixThread_Attributes", "PosixThread_Attributes\PosixThread_Attributes.vcxproj", "{CFEF4222-68AC-4D9C-98D2-E0E2181277E4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CFEF4222-68AC-4D9C-98D2-E0E2181277E4}.Debug|x64.ActiveCfg = Debug|x64 + {CFEF4222-68AC-4D9C-98D2-E0E2181277E4}.Debug|x64.Build.0 = Debug|x64 + {CFEF4222-68AC-4D9C-98D2-E0E2181277E4}.Debug|x86.ActiveCfg = Debug|Win32 + {CFEF4222-68AC-4D9C-98D2-E0E2181277E4}.Debug|x86.Build.0 = Debug|Win32 + {CFEF4222-68AC-4D9C-98D2-E0E2181277E4}.Release|x64.ActiveCfg = Release|x64 + {CFEF4222-68AC-4D9C-98D2-E0E2181277E4}.Release|x64.Build.0 = Release|x64 + {CFEF4222-68AC-4D9C-98D2-E0E2181277E4}.Release|x86.ActiveCfg = Release|Win32 + {CFEF4222-68AC-4D9C-98D2-E0E2181277E4}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B1D908A1-8B3F-4C04-9913-124FC142A4A3} + EndGlobalSection +EndGlobal diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Attributes/PosixThread_Attributes/PosixThread_Attributes.cpp" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Attributes/PosixThread_Attributes/PosixThread_Attributes.cpp" new file mode 100644 index 0000000..0b34693 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Attributes/PosixThread_Attributes/PosixThread_Attributes.cpp" @@ -0,0 +1,43 @@ +// PosixThread_HelloWorld.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 +// + +#include "pch.h" +#include +#include + +using namespace std; + + +int main() +{ + pthread_t t1; + + // 申明 POSIX Thread 属性变量 + pthread_attr_t attr; + // 申请线程栈大小(无符号整型) 512 K + size_t stack_size = 512 * 1000; + + // 初始化 pthread_attr_t + pthread_attr_init(&attr); + // 设置 pthread_attr_t 栈大小 -> 512 K + pthread_attr_setstacksize(&attr, stack_size); + + // 创建 t1 线程,并且将执行对象指向 void* helloWorld(void* ptr); + int result = pthread_create(&t1, &attr, helloWorld, NULL); + + pthread_join(t1, NULL); + // 销毁 pthread_attr_t attr + pthread_attr_destroy(&attr); + //线程退出 + pthread_exit(NULL); + + return EXIT_SUCCESS; +} + +void* helloWorld(void* ptr) { + pthread_t t = pthread_self(); + //printf("Thread - Hello World \n"); + cout << "Hello World" << endl; + return NULL; +} + diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Attributes/PosixThread_Attributes/PosixThread_Attributes.vcxproj" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Attributes/PosixThread_Attributes/PosixThread_Attributes.vcxproj" new file mode 100644 index 0000000..c5882e7 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Attributes/PosixThread_Attributes/PosixThread_Attributes.vcxproj" @@ -0,0 +1,171 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {CFEF4222-68AC-4D9C-98D2-E0E2181277E4} + Win32Proj + PosixThreadAttributes + 10.0.17763.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + E:\software\dev\CPP\pthreads-w32-2-9-1\Pre-built.2\include;$(IncludePath) + E:\software\dev\CPP\pthreads-w32-2-9-1\Pre-built.2\dll\x86;$(LibraryPath) + + + true + + + false + + + false + + + + Use + Level3 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + + + Console + true + E:\software\dev\CPP\pthreads-w32-2-9-1\Pre-built.2\lib\x86\pthreadVC2.lib;%(AdditionalDependencies) + + + + + Use + Level3 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + + + Console + true + + + + + Use + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + + + Console + true + true + true + + + + + Use + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + + + Console + true + true + true + + + + + + + + Create + Create + Create + Create + + + + + + + \ No newline at end of file diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Attributes/PosixThread_Attributes/PosixThread_Attributes.vcxproj.filters" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Attributes/PosixThread_Attributes/PosixThread_Attributes.vcxproj.filters" new file mode 100644 index 0000000..9b6edfc --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Attributes/PosixThread_Attributes/PosixThread_Attributes.vcxproj.filters" @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 头文件 + + + + + 源文件 + + + 源文件 + + + \ No newline at end of file diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Attributes/PosixThread_Attributes/PosixThread_Attributes.vcxproj.user" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Attributes/PosixThread_Attributes/PosixThread_Attributes.vcxproj.user" new file mode 100644 index 0000000..be25078 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Attributes/PosixThread_Attributes/PosixThread_Attributes.vcxproj.user" @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Attributes/PosixThread_Attributes/pch.cpp" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Attributes/PosixThread_Attributes/pch.cpp" new file mode 100644 index 0000000..8eb50d0 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Attributes/PosixThread_Attributes/pch.cpp" @@ -0,0 +1,5 @@ +// pch.cpp: 与预编译标头对应的源文件;编译成功所必需的 + +#include "pch.h" + +// 一般情况下,忽略此文件,但如果你使用的是预编译标头,请保留它。 diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Attributes/PosixThread_Attributes/pch.h" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Attributes/PosixThread_Attributes/pch.h" new file mode 100644 index 0000000..bd62e27 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Attributes/PosixThread_Attributes/pch.h" @@ -0,0 +1,15 @@ +// 入门提示: +// 1. 使用解决方案资源管理器窗口添加/管理文件 +// 2. 使用团队资源管理器窗口连接到源代码管理 +// 3. 使用输出窗口查看生成输出和其他消息 +// 4. 使用错误列表窗口查看错误 +// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目 +// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件 + +#ifndef PCH_H +#define PCH_H + +void* helloWorld(void* ptr); +// TODO: 添加要在此处预编译的标头 + +#endif //PCH_H diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_HelloWorld/PosixThread_HelloWorld.sln" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_HelloWorld/PosixThread_HelloWorld.sln" new file mode 100644 index 0000000..086b867 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_HelloWorld/PosixThread_HelloWorld.sln" @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.438 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PosixThread_HelloWorld", "PosixThread_HelloWorld\PosixThread_HelloWorld.vcxproj", "{F6804956-219B-4853-A162-6F85685868C5}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F6804956-219B-4853-A162-6F85685868C5}.Debug|x64.ActiveCfg = Debug|x64 + {F6804956-219B-4853-A162-6F85685868C5}.Debug|x64.Build.0 = Debug|x64 + {F6804956-219B-4853-A162-6F85685868C5}.Debug|x86.ActiveCfg = Debug|Win32 + {F6804956-219B-4853-A162-6F85685868C5}.Debug|x86.Build.0 = Debug|Win32 + {F6804956-219B-4853-A162-6F85685868C5}.Release|x64.ActiveCfg = Release|x64 + {F6804956-219B-4853-A162-6F85685868C5}.Release|x64.Build.0 = Release|x64 + {F6804956-219B-4853-A162-6F85685868C5}.Release|x86.ActiveCfg = Release|Win32 + {F6804956-219B-4853-A162-6F85685868C5}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {EC1A5E13-B1F6-4EE9-A4CF-457F212A7707} + EndGlobalSection +EndGlobal diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_HelloWorld/PosixThread_HelloWorld/PosixThread_HelloWorld.cpp" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_HelloWorld/PosixThread_HelloWorld/PosixThread_HelloWorld.cpp" new file mode 100644 index 0000000..a51c3a9 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_HelloWorld/PosixThread_HelloWorld/PosixThread_HelloWorld.cpp" @@ -0,0 +1,36 @@ +// PosixThread_HelloWorld.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 +// + +#include "pch.h" +#include +#include + +using namespace std; + + +int main() +{ + pthread_t t1; + + pthread_attr_t attr; + + size_t stack_size = 512 * 1000; + + pthread_attr_setstacksize(&attr, stack_size); + + // 创建 t1 线程,并且将执行对象指向 void* helloWorld(void* ptr); + int result = pthread_create(&t1,&attr, helloWorld, NULL); + + + pthread_join(t1, NULL); + + return EXIT_SUCCESS; +} + +void* helloWorld(void* ptr) { + pthread_t t = pthread_self(); + //printf("Thread - Hello World \n"); + cout << "Hello World" << endl; + return NULL; +} + diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_HelloWorld/PosixThread_HelloWorld/PosixThread_HelloWorld.vcxproj" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_HelloWorld/PosixThread_HelloWorld/PosixThread_HelloWorld.vcxproj" new file mode 100644 index 0000000..2dabff4 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_HelloWorld/PosixThread_HelloWorld/PosixThread_HelloWorld.vcxproj" @@ -0,0 +1,171 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {F6804956-219B-4853-A162-6F85685868C5} + Win32Proj + PosixThreadHelloWorld + 10.0.17763.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + E:\software\dev\CPP\pthreads-w32-2-9-1\Pre-built.2\include;$(IncludePath) + E:\software\dev\CPP\pthreads-w32-2-9-1\Pre-built.2\lib;$(LibraryPath) + + + true + + + false + + + false + + + + Use + Level3 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + + + Console + true + E:\software\dev\CPP\pthreads-w32-2-9-1\Pre-built.2\lib\x86\pthreadVC2.lib;%(AdditionalDependencies) + + + + + Use + Level3 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + + + Console + true + + + + + Use + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + + + Console + true + true + true + + + + + Use + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + + + Console + true + true + true + + + + + + + + Create + Create + Create + Create + + + + + + + \ No newline at end of file diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_HelloWorld/PosixThread_HelloWorld/PosixThread_HelloWorld.vcxproj.filters" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_HelloWorld/PosixThread_HelloWorld/PosixThread_HelloWorld.vcxproj.filters" new file mode 100644 index 0000000..1dcd5b5 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_HelloWorld/PosixThread_HelloWorld/PosixThread_HelloWorld.vcxproj.filters" @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 头文件 + + + + + 源文件 + + + 源文件 + + + \ No newline at end of file diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_HelloWorld/PosixThread_HelloWorld/PosixThread_HelloWorld.vcxproj.user" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_HelloWorld/PosixThread_HelloWorld/PosixThread_HelloWorld.vcxproj.user" new file mode 100644 index 0000000..be25078 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_HelloWorld/PosixThread_HelloWorld/PosixThread_HelloWorld.vcxproj.user" @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_HelloWorld/PosixThread_HelloWorld/pch.cpp" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_HelloWorld/PosixThread_HelloWorld/pch.cpp" new file mode 100644 index 0000000..8eb50d0 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_HelloWorld/PosixThread_HelloWorld/pch.cpp" @@ -0,0 +1,5 @@ +// pch.cpp: 与预编译标头对应的源文件;编译成功所必需的 + +#include "pch.h" + +// 一般情况下,忽略此文件,但如果你使用的是预编译标头,请保留它。 diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_HelloWorld/PosixThread_HelloWorld/pch.h" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_HelloWorld/PosixThread_HelloWorld/pch.h" new file mode 100644 index 0000000..3dc472d --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_HelloWorld/PosixThread_HelloWorld/pch.h" @@ -0,0 +1,16 @@ +// 入门提示: +// 1. 使用解决方案资源管理器窗口添加/管理文件 +// 2. 使用团队资源管理器窗口连接到源代码管理 +// 3. 使用输出窗口查看生成输出和其他消息 +// 4. 使用错误列表窗口查看错误 +// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目 +// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件 + +#ifndef PCH_H +#define PCH_H + +// TODO: 添加要在此处预编译的标头 + +void* helloWorld(void* ptr); + +#endif //PCH_H diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Sync/PosixThread_Sync.sln" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Sync/PosixThread_Sync.sln" new file mode 100644 index 0000000..0d143e5 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Sync/PosixThread_Sync.sln" @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.438 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PosixThread_Sync", "PosixThread_Sync\PosixThread_Sync.vcxproj", "{186FD364-9C46-475A-B433-7C56CCA71E90}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {186FD364-9C46-475A-B433-7C56CCA71E90}.Debug|x64.ActiveCfg = Debug|x64 + {186FD364-9C46-475A-B433-7C56CCA71E90}.Debug|x64.Build.0 = Debug|x64 + {186FD364-9C46-475A-B433-7C56CCA71E90}.Debug|x86.ActiveCfg = Debug|Win32 + {186FD364-9C46-475A-B433-7C56CCA71E90}.Debug|x86.Build.0 = Debug|Win32 + {186FD364-9C46-475A-B433-7C56CCA71E90}.Release|x64.ActiveCfg = Release|x64 + {186FD364-9C46-475A-B433-7C56CCA71E90}.Release|x64.Build.0 = Release|x64 + {186FD364-9C46-475A-B433-7C56CCA71E90}.Release|x86.ActiveCfg = Release|Win32 + {186FD364-9C46-475A-B433-7C56CCA71E90}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D6EDBBD3-9280-49C2-9BCB-2A6D087E8082} + EndGlobalSection +EndGlobal diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Sync/PosixThread_Sync/PosixThread_Sync.cpp" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Sync/PosixThread_Sync/PosixThread_Sync.cpp" new file mode 100644 index 0000000..a910ae8 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Sync/PosixThread_Sync/PosixThread_Sync.cpp" @@ -0,0 +1,82 @@ +// PosixThread_Sync.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 +// + +#include "pch.h" +#include +#include + +int counter = 0; + +// 定义互斥对象 +pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; + +// 定义条件变量 +pthread_cond_t condition_var = PTHREAD_COND_INITIALIZER; + +void* addCounter(void* ptr); + +void* minusCounter(void* ptr); + +int main() +{ + pthread_t t1; + pthread_t t2; + + pthread_create(&t1, NULL, addCounter, NULL); + pthread_create(&t2, NULL, minusCounter, NULL); + + + pthread_join(t1, NULL); + pthread_join(t2, NULL); + + std::cout << "Counter : " << counter << std::endl; + + return EXIT_SUCCESS; +} + +void* minusCounter(void* ptr) { + for (int i=0;i<100;i++) { + + // lock 加锁 + pthread_mutex_lock(&mutex1); + std::cout << "minusCounter - Before Counter : " << counter << std::endl; + + if (counter < 9 && counter > 1) { // 消费数据,唤起生产者线程 + counter--; + pthread_cond_signal(&condition_var); + } + + if (counter < 1) { // 当数据不足时,阻塞当前消费者线程 + pthread_cond_wait(&condition_var, &mutex1); + } + + + std::cout << "minusCounter - After Counter : " << counter << std::endl; + // unlock 解锁 + pthread_mutex_unlock(&mutex1); + } + return NULL; +} + +void* addCounter(void* ptr) { + for (int i = 0; i < 100; i++) { + // lock 加锁 + pthread_mutex_lock(&mutex1); + std::cout << "addCounter - Before Counter : " << counter << std::endl; + + if (counter < 9) { // 当数据不到阈值时,唤起当前消费者线程 + counter++; + pthread_cond_signal(&condition_var); + } + + if (counter > 9) { // 当数据达到阈值时,阻塞当前生产者线程 + pthread_cond_wait(&condition_var, &mutex1); + } + + std::cout << "addCounter - After Counter : " << counter << std::endl; + // unlock 解锁 + pthread_mutex_unlock(&mutex1); + } + return NULL; +} + diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Sync/PosixThread_Sync/PosixThread_Sync.vcxproj" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Sync/PosixThread_Sync/PosixThread_Sync.vcxproj" new file mode 100644 index 0000000..19d03b2 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Sync/PosixThread_Sync/PosixThread_Sync.vcxproj" @@ -0,0 +1,174 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {186FD364-9C46-475A-B433-7C56CCA71E90} + Win32Proj + PosixThreadSync + 10.0.17763.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + E:\software\dev\CPP\pthreads-w32-2-9-1\Pre-built.2\include;$(IncludePath) + E:\software\dev\CPP\pthreads-w32-2-9-1\Pre-built.2\dll\x86;$(LibraryPath) + + + true + E:\software\dev\CPP\pthreads-w32-2-9-1\Pre-built.2\include;$(IncludePath) + E:\software\dev\CPP\pthreads-w32-2-9-1\Pre-built.2\dll\x86;$(LibraryPath) + + + false + + + false + + + + Use + Level3 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + + + Console + true + E:\software\dev\CPP\pthreads-w32-2-9-1\Pre-built.2\lib\x86\pthreadVC2.lib;%(AdditionalDependencies) + + + + + Use + Level3 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + + + Console + true + E:\software\dev\CPP\pthreads-w32-2-9-1\Pre-built.2\lib\x86\pthreadVC2.lib;%(AdditionalDependencies) + + + + + Use + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + + + Console + true + true + true + + + + + Use + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + + + Console + true + true + true + + + + + + + + Create + Create + Create + Create + + + + + + + \ No newline at end of file diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Sync/PosixThread_Sync/PosixThread_Sync.vcxproj.filters" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Sync/PosixThread_Sync/PosixThread_Sync.vcxproj.filters" new file mode 100644 index 0000000..19b500b --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Sync/PosixThread_Sync/PosixThread_Sync.vcxproj.filters" @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 头文件 + + + + + 源文件 + + + 源文件 + + + \ No newline at end of file diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Sync/PosixThread_Sync/PosixThread_Sync.vcxproj.user" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Sync/PosixThread_Sync/PosixThread_Sync.vcxproj.user" new file mode 100644 index 0000000..be25078 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Sync/PosixThread_Sync/PosixThread_Sync.vcxproj.user" @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Sync/PosixThread_Sync/pch.cpp" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Sync/PosixThread_Sync/pch.cpp" new file mode 100644 index 0000000..8eb50d0 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Sync/PosixThread_Sync/pch.cpp" @@ -0,0 +1,5 @@ +// pch.cpp: 与预编译标头对应的源文件;编译成功所必需的 + +#include "pch.h" + +// 一般情况下,忽略此文件,但如果你使用的是预编译标头,请保留它。 diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Sync/PosixThread_Sync/pch.h" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Sync/PosixThread_Sync/pch.h" new file mode 100644 index 0000000..69bf59d --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\344\273\243\347\240\201/segmentfault/visual-studio-workspace/PosixThread_Sync/PosixThread_Sync/pch.h" @@ -0,0 +1,14 @@ +// 入门提示: +// 1. 使用解决方案资源管理器窗口添加/管理文件 +// 2. 使用团队资源管理器窗口连接到源代码管理 +// 3. 使用输出窗口查看生成输出和其他消息 +// 4. 使用错误列表窗口查看错误 +// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目 +// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件 + +#ifndef PCH_H +#define PCH_H + +// TODO: 添加要在此处预编译的标头 + +#endif //PCH_H diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\270\211\346\234\237/\347\254\254\344\270\200\350\212\202 Java \347\272\277\347\250\213\344\270\216\350\277\233\347\250\213/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\344\270\211\346\234\237 \347\254\254\344\270\200\350\212\202 \343\200\212Java \347\272\277\347\250\213\344\270\216\350\277\233\347\250\213\343\200\213.pdf" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\270\211\346\234\237/\347\254\254\344\270\200\350\212\202 Java \347\272\277\347\250\213\344\270\216\350\277\233\347\250\213/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\344\270\211\346\234\237 \347\254\254\344\270\200\350\212\202 \343\200\212Java \347\272\277\347\250\213\344\270\216\350\277\233\347\250\213\343\200\213.pdf" new file mode 100644 index 0000000..05e6211 Binary files /dev/null and "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\270\211\346\234\237/\347\254\254\344\270\200\350\212\202 Java \347\272\277\347\250\213\344\270\216\350\277\233\347\250\213/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\344\270\211\346\234\237 \347\254\254\344\270\200\350\212\202 \343\200\212Java \347\272\277\347\250\213\344\270\216\350\277\233\347\250\213\343\200\213.pdf" differ diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\270\211\346\234\237/\347\254\254\344\270\211\350\212\202 Java \345\271\266\345\217\221\346\241\206\346\236\266\345\237\272\347\241\200\350\277\220\347\224\250/Multithreading-and-Concurrency-Questions.pdf" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\270\211\346\234\237/\347\254\254\344\270\211\350\212\202 Java \345\271\266\345\217\221\346\241\206\346\236\266\345\237\272\347\241\200\350\277\220\347\224\250/Multithreading-and-Concurrency-Questions.pdf" new file mode 100644 index 0000000..93e9275 Binary files /dev/null and "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\270\211\346\234\237/\347\254\254\344\270\211\350\212\202 Java \345\271\266\345\217\221\346\241\206\346\236\266\345\237\272\347\241\200\350\277\220\347\224\250/Multithreading-and-Concurrency-Questions.pdf" differ diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\270\211\346\234\237/\347\254\254\344\270\211\350\212\202 Java \345\271\266\345\217\221\346\241\206\346\236\266\345\237\272\347\241\200\350\277\220\347\224\250/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\344\270\211\346\234\237 \347\254\254\344\270\211\350\212\202 \343\200\212Java \345\271\266\345\217\221\346\241\206\346\236\266\345\237\272\347\241\200\350\277\220\347\224\250\343\200\213.pdf" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\270\211\346\234\237/\347\254\254\344\270\211\350\212\202 Java \345\271\266\345\217\221\346\241\206\346\236\266\345\237\272\347\241\200\350\277\220\347\224\250/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\344\270\211\346\234\237 \347\254\254\344\270\211\350\212\202 \343\200\212Java \345\271\266\345\217\221\346\241\206\346\236\266\345\237\272\347\241\200\350\277\220\347\224\250\343\200\213.pdf" new file mode 100644 index 0000000..106481c Binary files /dev/null and "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\270\211\346\234\237/\347\254\254\344\270\211\350\212\202 Java \345\271\266\345\217\221\346\241\206\346\236\266\345\237\272\347\241\200\350\277\220\347\224\250/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\344\270\211\346\234\237 \347\254\254\344\270\211\350\212\202 \343\200\212Java \345\271\266\345\217\221\346\241\206\346\236\266\345\237\272\347\241\200\350\277\220\347\224\250\343\200\213.pdf" differ diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\270\211\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\271\266\345\217\221\347\274\226\347\250\213\345\237\272\347\241\200/Christoph Lameter, Ph.D. - 2005 - Effective Synchronization.pdf" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\270\211\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\271\266\345\217\221\347\274\226\347\250\213\345\237\272\347\241\200/Christoph Lameter, Ph.D. - 2005 - Effective Synchronization.pdf" new file mode 100644 index 0000000..76d02ac Binary files /dev/null and "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\270\211\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\271\266\345\217\221\347\274\226\347\250\213\345\237\272\347\241\200/Christoph Lameter, Ph.D. - 2005 - Effective Synchronization.pdf" differ diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\270\211\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\271\266\345\217\221\347\274\226\347\250\213\345\237\272\347\241\200/Dave Dice - 2006 - Synchronization in Java SE 6(HotSpot).pdf" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\270\211\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\271\266\345\217\221\347\274\226\347\250\213\345\237\272\347\241\200/Dave Dice - 2006 - Synchronization in Java SE 6(HotSpot).pdf" new file mode 100644 index 0000000..f93e6a3 Binary files /dev/null and "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\270\211\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\271\266\345\217\221\347\274\226\347\250\213\345\237\272\347\241\200/Dave Dice - 2006 - Synchronization in Java SE 6(HotSpot).pdf" differ diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\270\211\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\271\266\345\217\221\347\274\226\347\250\213\345\237\272\347\241\200/Thin Locks Featherweight Synchronization for Java.pdf" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\270\211\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\271\266\345\217\221\347\274\226\347\250\213\345\237\272\347\241\200/Thin Locks Featherweight Synchronization for Java.pdf" new file mode 100644 index 0000000..70a03e1 Binary files /dev/null and "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\270\211\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\271\266\345\217\221\347\274\226\347\250\213\345\237\272\347\241\200/Thin Locks Featherweight Synchronization for Java.pdf" differ diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\270\211\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\271\266\345\217\221\347\274\226\347\250\213\345\237\272\347\241\200/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\344\270\211\346\234\237 \347\254\254\344\272\214\350\212\202 \343\200\212Java \345\271\266\345\217\221\347\274\226\347\250\213\345\237\272\347\241\200\343\200\213.pdf" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\270\211\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\271\266\345\217\221\347\274\226\347\250\213\345\237\272\347\241\200/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\344\270\211\346\234\237 \347\254\254\344\272\214\350\212\202 \343\200\212Java \345\271\266\345\217\221\347\274\226\347\250\213\345\237\272\347\241\200\343\200\213.pdf" new file mode 100644 index 0000000..8536d52 Binary files /dev/null and "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\270\211\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\271\266\345\217\221\347\274\226\347\250\213\345\237\272\347\241\200/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\344\270\211\346\234\237 \347\254\254\344\272\214\350\212\202 \343\200\212Java \345\271\266\345\217\221\347\274\226\347\250\213\345\237\272\347\241\200\343\200\213.pdf" differ diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\270\211\346\234\237/\347\254\254\345\233\233\350\212\202 Java \345\271\266\345\217\221\346\241\206\346\236\266\351\253\230\347\272\247\350\277\220\347\224\250/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\344\270\211\346\234\237 \347\254\254\345\233\233\350\212\202 \343\200\212Java \345\271\266\345\217\221\346\241\206\346\236\266\351\253\230\347\272\247\350\277\220\347\224\250\343\200\213.pdf" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\270\211\346\234\237/\347\254\254\345\233\233\350\212\202 Java \345\271\266\345\217\221\346\241\206\346\236\266\351\253\230\347\272\247\350\277\220\347\224\250/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\344\270\211\346\234\237 \347\254\254\345\233\233\350\212\202 \343\200\212Java \345\271\266\345\217\221\346\241\206\346\236\266\351\253\230\347\272\247\350\277\220\347\224\250\343\200\213.pdf" new file mode 100644 index 0000000..502c3d6 Binary files /dev/null and "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\270\211\346\234\237/\347\254\254\345\233\233\350\212\202 Java \345\271\266\345\217\221\346\241\206\346\236\266\351\253\230\347\272\247\350\277\220\347\224\250/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\344\270\211\346\234\237 \347\254\254\345\233\233\350\212\202 \343\200\212Java \345\271\266\345\217\221\346\241\206\346\236\266\351\253\230\347\272\247\350\277\220\347\224\250\343\200\213.pdf" differ diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\272\224\346\234\237/\347\233\270\345\205\263\350\265\204\346\226\231/2006 - Memory Management in the Java HotSpot\342\204\242 Virtual Machine .pdf" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\272\224\346\234\237/\347\233\270\345\205\263\350\265\204\346\226\231/2006 - Memory Management in the Java HotSpot\342\204\242 Virtual Machine .pdf" new file mode 100644 index 0000000..5f113ca Binary files /dev/null and "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\272\224\346\234\237/\347\233\270\345\205\263\350\265\204\346\226\231/2006 - Memory Management in the Java HotSpot\342\204\242 Virtual Machine .pdf" differ diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\272\224\346\234\237/\347\254\254\344\270\200\350\212\202 Java \347\261\273\347\232\204\345\261\202\346\254\241/README.md" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\272\224\346\234\237/\347\254\254\344\270\200\350\212\202 Java \347\261\273\347\232\204\345\261\202\346\254\241/README.md" new file mode 100644 index 0000000..246e4b3 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\272\224\346\234\237/\347\254\254\344\270\200\350\212\202 Java \347\261\273\347\232\204\345\261\202\346\254\241/README.md" @@ -0,0 +1,334 @@ +# 「一入 Java 深似海 」系列 第五期 第一节 《Java 类的层次》 + + + +## JVM 小常识 + +### native 源码路径 + +通常 XXX.java 出现 native 方法时,对应的 JVM 源码实现则为 XXX.c 文件,比如: + +- java.lang.Class -> share/native/java/lang/Class.c +- java.lang.ClassLoader -> share/native/java/lang/ClassLoader.c + + + +### native 方法注册机制 + +Java Class 文件中的 `registerNatives()` 方法,以 `java.lang.Class` 为例: + +```java + private static native void registerNatives(); + static { + registerNatives(); + } +``` + + + +对应的 JVM 实现: + +```c +JNIEXPORT void JNICALL +Java_java_lang_Class_registerNatives(JNIEnv *env, jclass cls) +{ + methods[1].fnPtr = (void *)(*env)->GetSuperclass; + (*env)->RegisterNatives(env, cls, methods, + sizeof(methods)/sizeof(JNINativeMethod)); +} +``` + + + +其中 `JNINativeMethod` 是数据结构,`methods` 是函数指针(地址): + +```c +static JNINativeMethod methods[] = { + {"getName0", "()" STR, (void *)&JVM_GetClassName}, + {"getSuperclass", "()" CLS, NULL}, + {"getInterfaces0", "()[" CLS, (void *)&JVM_GetClassInterfaces}, + {"getClassLoader0", "()" JCL, (void *)&JVM_GetClassLoader}, + {"isInterface", "()Z", (void *)&JVM_IsInterface}, + {"getSigners", "()[" OBJ, (void *)&JVM_GetClassSigners}, + {"setSigners", "([" OBJ ")V", (void *)&JVM_SetClassSigners}, + {"isArray", "()Z", (void *)&JVM_IsArrayClass}, + {"isPrimitive", "()Z", (void *)&JVM_IsPrimitiveClass}, + {"getComponentType", "()" CLS, (void *)&JVM_GetComponentType}, + {"getModifiers", "()I", (void *)&JVM_GetClassModifiers}, + {"getDeclaredFields0","(Z)[" FLD, (void *)&JVM_GetClassDeclaredFields}, + {"getDeclaredMethods0","(Z)[" MHD, (void *)&JVM_GetClassDeclaredMethods}, + {"getDeclaredConstructors0","(Z)[" CTR, (void *)&JVM_GetClassDeclaredConstructors}, + {"getProtectionDomain0", "()" PD, (void *)&JVM_GetProtectionDomain}, + {"getDeclaredClasses0", "()[" CLS, (void *)&JVM_GetDeclaredClasses}, + {"getDeclaringClass0", "()" CLS, (void *)&JVM_GetDeclaringClass}, + {"getGenericSignature0", "()" STR, (void *)&JVM_GetClassSignature}, + {"getRawAnnotations", "()" BA, (void *)&JVM_GetClassAnnotations}, + {"getConstantPool", "()" CPL, (void *)&JVM_GetClassConstantPool}, + {"desiredAssertionStatus0","("CLS")Z",(void *)&JVM_DesiredAssertionStatus}, + {"getEnclosingMethod0", "()[" OBJ, (void *)&JVM_GetEnclosingMethodInfo}, + {"getRawTypeAnnotations", "()" BA, (void *)&JVM_GetClassTypeAnnotations}, +}; +``` + +例如:`getName0` 方法是来自于 Java native 方法名, `JVM_GetClassName` 是 JVM C 实现函数: + +```c +JVM_ENTRY(jstring, JVM_GetClassName(JNIEnv *env, jclass cls)) + assert (cls != NULL, "illegal class"); + JVMWrapper("JVM_GetClassName"); + JvmtiVMObjectAllocEventCollector oam; + ResourceMark rm(THREAD); + const char* name; + if (java_lang_Class::is_primitive(JNIHandles::resolve(cls))) { + name = type2name(java_lang_Class::primitive_type(JNIHandles::resolve(cls))); + } else { + // Consider caching interned string in Klass + Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls)); + assert(k->is_klass(), "just checking"); + name = k->external_name(); + } + oop result = StringTable::intern((char*) name, CHECK_NULL); + return (jstring) JNIHandles::make_local(env, result); +JVM_END +``` + + + +### JVM Header 与 Source 文件的映射 + +header 文件是`.hpp` 存储,source 文件是对应的 `.cpp` 文件。 + + + +### 重要方法 JNIHandles::resolve + +将 JNI jxxx 对象转化成 oop 对象 + + + +### 重要文件 + + + +#### allocation.hpp 以及 allocation.cpp 文件 + +- ResourceObj + +For objects allocated in the resource area (see resourceArea.hpp). + +- CHeapObj + + For objects allocated in the C-heap (managed by: free & malloc). + +- StackObj + +For objects allocated on the stack. + +- ValueObj + +For embedded objects. + +- AllStatic + +For classes used as name spaces. + +- MetaspaceObj + +For classes in Metaspace (class data) + + + + +## Java 类对象 + + + +### 基本概念 + +类对象 = Class 对象 = `.class` + + + +### 基本分类 + +对象类型:`Object.class` 以及派生类 + +原生类型:`int`、`long` 等 + +类定义 = 原生+对象字段作为存储状态 + 方法来控制状态行为 + + + + + +### 基础知识 + + + +#### 类的版本 + +类的版本属于 Java 虚拟机规范:JVM 以及 Class + +> Java 语言规范:JDK 和 Java 运行时语法、行为控制 + + + +#### 编译器 + +- javac - Java 程序编写的可执行程序(since 6 开始,通过 Java 实现,6 之前,native 实现)(Maven 编译器插件) + +- ecj - eclipse 编译器,JSP 编译器(JSP 翻译 JSP .java 文件,编译成 JSP .class 文件),Eclipse IDE(注意 Java 泛型差异) + + > JSP - JspServlet 运行时参数 development = true -> false + +> javac 与 eclipse 编译器不一定完全兼容 + + + +#### Class 与 ClassLoader 之间的关系 + +Java Class 的元(meta)信息定义在 .class 文件中,类版本号、魔数、类结构、字节码等等 + + + +ClassLoader 是按照字节码规则加载 Class 资源(.class 文件 ,网络传输),形成 Java 运行时 Class 对象 + + + +1. ClassLoader#loadClass 是用于加载 Class 对象,那么 Class 对象是被那个 ClassLoader 加载的? + +Class 对象是通过 ClassLoader 的 loadClass 方法加载并获取,相反,ClassLoader 可以通过 Class 的 getClassLoader() 获取。 + + + +2. Class 对象可能来自于文件(如 .class 文件),也可能是来自于网络,那么 ClassLoader 是如何将这些资源变为 Class 对象 + +.class 文件或者网络 I/O 都是字节码流(Stream),ClassLoader 能够把二进制流解析为 Class 对象,通过复用 ClassLoader#defineClass 方法实现(重)定义 Class 类,比如 Groovy 动态加载类。 + + + +3. Class 对象与 ClassLoader#loadClass 方法之间的关联? + +ClassLoader#loadClass 时,通过 ClassPath 关联类资源(文件、网络),来获取字节码流,再被定义 Class 对象。 + + + +ClassLoader 类加载顺序: + +- 尝试已加载的类( ClassLoader 层次性,要不当前 ClassLoader,要不其 Parent) + +- 尝试双亲委派加载类(直到 Bootstrap ClassLoader 加载不到) +- 执行 findClass(String) 方法(ClassLoader 是一个抛出 ClassNotFoundException 实现,子类可覆盖该方法) + - jdk.internal.loader.BuiltinClassLoader#findClass + - ClassPath = URLClassPath + + + +#### 系统 ClassLaoder 实现 + + + +##### Java 12 中的实现 + +- jdk.internal.loader.ClassLoaders.AppClassLoader + - jdk.internal.loader.BuiltinClassLoader + - java.security.SecureClassLoader + - java.lang.ClassLoader + + + +#### ClassLoader 双亲委派 + + + +`ClassLoader` 提供 parent 字段引用双亲 ClassLoader,通常调用 loadClass(String) 方法: + +```java + public Class loadClass(String name) throws ClassNotFoundException { + return loadClass(name, false); + } +``` + +双亲委派类加载实际是通过 `parent` 字段递归,找到根 ClassLoader。实际上,根 ClassLoader = Bootstrap ClassLoader + +loadClass(String) 方法 不仅可被 Java 程序调用,比如:Spring BeanFactory 类加载时,也可能被 JVM 调用,比如:new XXX()时,XXX 将作为类被加载。 + +#### JVM 调用 loadClass 方法的时机 + +- new XXX() 时 +- 调用 XXX.yyy 静态字段 +- 通过反射 API - `Class.forName` 或者 ` ClassLoader.loadClass` + + + +#### 原生类型 Class 对象 + + + +```java +// 原生类型也有类对象 +Class intClas = int.class; +``` + +#### Bootstrap ClassLoader + +等价于: +```java + Class findBootstrapClassOrNull(String name) { + if (!checkName(name)) return null; + + return findBootstrapClass(name); + } + + // return null if not found + private native Class findBootstrapClass(String name); +``` + + + +#### ClassLoader + +Bootstrap ClassLoader 是无法获取,最接近 Java 程序的 ClassLoader 是 System ClassLoader + + + +##### 系统 ClassLoader + +通过 `java.lang.ClassLoader#getSystemClassLoader` 方法获取。 + +##### 应用 ClassLoader + +可以通过当前 Thread 上下文 ClassLoader 获取(不完全一定):`java.lang.Thread#getContextClassLoader` + + + + + +#### 相关书籍 + +《深入 Java 虚拟机》- 1999 年 + + + +## Java 类存储 + +Java 中的 Class 类 对应的 JVM 结构 Klass 类,由于Class 类存储从 Java 8 + 放置 Metadata 区域,不在是 Perm: + +```c++ +class Klass : public Metadata { + +} +``` + + + +> + + + +## Java 类装载和卸载 + + + + + diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\272\224\346\234\237/\347\254\254\344\270\200\350\212\202 Java \347\261\273\347\232\204\345\261\202\346\254\241/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\344\272\224\346\234\237 \347\254\254\344\270\200\350\212\202 \343\200\212Java \347\261\273\347\232\204\345\261\202\346\254\241\343\200\213.pdf" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\272\224\346\234\237/\347\254\254\344\270\200\350\212\202 Java \347\261\273\347\232\204\345\261\202\346\254\241/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\344\272\224\346\234\237 \347\254\254\344\270\200\350\212\202 \343\200\212Java \347\261\273\347\232\204\345\261\202\346\254\241\343\200\213.pdf" new file mode 100644 index 0000000..a911e82 Binary files /dev/null and "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\272\224\346\234\237/\347\254\254\344\270\200\350\212\202 Java \347\261\273\347\232\204\345\261\202\346\254\241/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\344\272\224\346\234\237 \347\254\254\344\270\200\350\212\202 \343\200\212Java \347\261\273\347\232\204\345\261\202\346\254\241\343\200\213.pdf" differ diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\272\224\346\234\237/\347\254\254\344\270\211\350\212\202 Java \344\274\240\347\273\237\345\236\203\345\234\276\346\224\266\351\233\206\345\231\250\357\274\210\344\270\212\357\274\211/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\344\272\224\346\234\237 \347\254\254\344\270\211\350\212\202 \343\200\212Java \344\274\240\347\273\237\345\236\203\345\234\276\346\224\266\351\233\206\345\231\250\357\274\210\344\270\212\357\274\211\343\200\213.pdf" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\272\224\346\234\237/\347\254\254\344\270\211\350\212\202 Java \344\274\240\347\273\237\345\236\203\345\234\276\346\224\266\351\233\206\345\231\250\357\274\210\344\270\212\357\274\211/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\344\272\224\346\234\237 \347\254\254\344\270\211\350\212\202 \343\200\212Java \344\274\240\347\273\237\345\236\203\345\234\276\346\224\266\351\233\206\345\231\250\357\274\210\344\270\212\357\274\211\343\200\213.pdf" new file mode 100644 index 0000000..a7b5c6f Binary files /dev/null and "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\272\224\346\234\237/\347\254\254\344\270\211\350\212\202 Java \344\274\240\347\273\237\345\236\203\345\234\276\346\224\266\351\233\206\345\231\250\357\274\210\344\270\212\357\274\211/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\344\272\224\346\234\237 \347\254\254\344\270\211\350\212\202 \343\200\212Java \344\274\240\347\273\237\345\236\203\345\234\276\346\224\266\351\233\206\345\231\250\357\274\210\344\270\212\357\274\211\343\200\213.pdf" differ diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\272\224\346\234\237/\347\254\254\344\272\224\350\212\202 Java \346\226\260\345\236\213\345\236\203\345\234\276\346\224\266\351\233\206\345\231\250/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\344\272\224\346\234\237 \347\254\254\344\272\224\350\212\202 \343\200\212Java \346\226\260\345\236\213\345\236\203\345\234\276\346\224\266\351\233\206\345\231\250\343\200\213.pdf" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\272\224\346\234\237/\347\254\254\344\272\224\350\212\202 Java \346\226\260\345\236\213\345\236\203\345\234\276\346\224\266\351\233\206\345\231\250/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\344\272\224\346\234\237 \347\254\254\344\272\224\350\212\202 \343\200\212Java \346\226\260\345\236\213\345\236\203\345\234\276\346\224\266\351\233\206\345\231\250\343\200\213.pdf" new file mode 100644 index 0000000..033f671 Binary files /dev/null and "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\272\224\346\234\237/\347\254\254\344\272\224\350\212\202 Java \346\226\260\345\236\213\345\236\203\345\234\276\346\224\266\351\233\206\345\231\250/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\344\272\224\346\234\237 \347\254\254\344\272\224\350\212\202 \343\200\212Java \346\226\260\345\236\213\345\236\203\345\234\276\346\224\266\351\233\206\345\231\250\343\200\213.pdf" differ diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\272\224\346\234\237/\347\254\254\345\233\233\350\212\202 Java \344\274\240\347\273\237\345\236\203\345\234\276\346\224\266\351\233\206\345\231\250\357\274\210\344\270\213\357\274\211/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\344\272\224\346\234\237 \347\254\254\345\233\233\350\212\202 \343\200\212Java \344\274\240\347\273\237\345\236\203\345\234\276\346\224\266\351\233\206\345\231\250\357\274\210\344\270\213\357\274\211\343\200\213.pdf" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\272\224\346\234\237/\347\254\254\345\233\233\350\212\202 Java \344\274\240\347\273\237\345\236\203\345\234\276\346\224\266\351\233\206\345\231\250\357\274\210\344\270\213\357\274\211/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\344\272\224\346\234\237 \347\254\254\345\233\233\350\212\202 \343\200\212Java \344\274\240\347\273\237\345\236\203\345\234\276\346\224\266\351\233\206\345\231\250\357\274\210\344\270\213\357\274\211\343\200\213.pdf" new file mode 100644 index 0000000..4f57027 Binary files /dev/null and "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\344\272\224\346\234\237/\347\254\254\345\233\233\350\212\202 Java \344\274\240\347\273\237\345\236\203\345\234\276\346\224\266\351\233\206\345\231\250\357\274\210\344\270\213\357\274\211/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\344\272\224\346\234\237 \347\254\254\345\233\233\350\212\202 \343\200\212Java \344\274\240\347\273\237\345\236\203\345\234\276\346\224\266\351\233\206\345\231\250\357\274\210\344\270\213\357\274\211\343\200\213.pdf" differ diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\344\270\200\350\212\202 POSIX Thread/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\345\233\233\346\234\237 \347\254\254\344\270\200\350\212\202 \343\200\212POSIX Thread\343\200\213.pdf" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\344\270\200\350\212\202 POSIX Thread/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\345\233\233\346\234\237 \347\254\254\344\270\200\350\212\202 \343\200\212POSIX Thread\343\200\213.pdf" new file mode 100644 index 0000000..5e05390 Binary files /dev/null and "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\344\270\200\350\212\202 POSIX Thread/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\345\233\233\346\234\237 \347\254\254\344\270\200\350\212\202 \343\200\212POSIX Thread\343\200\213.pdf" differ diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\344\270\211\350\212\202 Java \345\271\266\345\217\221\346\241\206\346\236\266\357\274\210J.U.C\357\274\211 AQS \345\216\237\347\220\206/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\345\233\233\346\234\237 \347\254\254\344\270\211\350\212\202\343\200\212Java \345\271\266\345\217\221\346\241\206\346\236\266\357\274\210J.U.C\357\274\211 AQS \345\216\237\347\220\206\343\200\213.pdf" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\344\270\211\350\212\202 Java \345\271\266\345\217\221\346\241\206\346\236\266\357\274\210J.U.C\357\274\211 AQS \345\216\237\347\220\206/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\345\233\233\346\234\237 \347\254\254\344\270\211\350\212\202\343\200\212Java \345\271\266\345\217\221\346\241\206\346\236\266\357\274\210J.U.C\357\274\211 AQS \345\216\237\347\220\206\343\200\213.pdf" new file mode 100644 index 0000000..4fbeb01 Binary files /dev/null and "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\344\270\211\350\212\202 Java \345\271\266\345\217\221\346\241\206\346\236\266\357\274\210J.U.C\357\274\211 AQS \345\216\237\347\220\206/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\345\233\233\346\234\237 \347\254\254\344\270\211\350\212\202\343\200\212Java \345\271\266\345\217\221\346\241\206\346\236\266\357\274\210J.U.C\357\274\211 AQS \345\216\237\347\220\206\343\200\213.pdf" differ diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\206\205\345\255\230\346\250\241\345\236\213\357\274\210Java Memory Model\357\274\211/JSR-133 Java Memory Model and Thread Specification.pdf" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\206\205\345\255\230\346\250\241\345\236\213\357\274\210Java Memory Model\357\274\211/JSR-133 Java Memory Model and Thread Specification.pdf" new file mode 100644 index 0000000..c07d385 Binary files /dev/null and "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\206\205\345\255\230\346\250\241\345\236\213\357\274\210Java Memory Model\357\274\211/JSR-133 Java Memory Model and Thread Specification.pdf" differ diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\206\205\345\255\230\346\250\241\345\236\213\357\274\210Java Memory Model\357\274\211/JavaOne 2004 - The New Java\342\204\242 Technology Memory Model.pdf" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\206\205\345\255\230\346\250\241\345\236\213\357\274\210Java Memory Model\357\274\211/JavaOne 2004 - The New Java\342\204\242 Technology Memory Model.pdf" new file mode 100644 index 0000000..739beab Binary files /dev/null and "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\206\205\345\255\230\346\250\241\345\236\213\357\274\210Java Memory Model\357\274\211/JavaOne 2004 - The New Java\342\204\242 Technology Memory Model.pdf" differ diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\206\205\345\255\230\346\250\241\345\236\213\357\274\210Java Memory Model\357\274\211/The Java Language Specification Java SE 12 Edition.pdf" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\206\205\345\255\230\346\250\241\345\236\213\357\274\210Java Memory Model\357\274\211/The Java Language Specification Java SE 12 Edition.pdf" new file mode 100644 index 0000000..0ce39bc Binary files /dev/null and "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\206\205\345\255\230\346\250\241\345\236\213\357\274\210Java Memory Model\357\274\211/The Java Language Specification Java SE 12 Edition.pdf" differ diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\206\205\345\255\230\346\250\241\345\236\213\357\274\210Java Memory Model\357\274\211/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\345\233\233\346\234\237 \347\254\254\344\272\214\350\212\202\343\200\212Java \345\206\205\345\255\230\346\250\241\345\236\213\357\274\210Java Memory Model\357\274\211\343\200\213.pdf" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\206\205\345\255\230\346\250\241\345\236\213\357\274\210Java Memory Model\357\274\211/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\345\233\233\346\234\237 \347\254\254\344\272\214\350\212\202\343\200\212Java \345\206\205\345\255\230\346\250\241\345\236\213\357\274\210Java Memory Model\357\274\211\343\200\213.pdf" new file mode 100644 index 0000000..b43767b Binary files /dev/null and "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\206\205\345\255\230\346\250\241\345\236\213\357\274\210Java Memory Model\357\274\211/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\345\233\233\346\234\237 \347\254\254\344\272\214\350\212\202\343\200\212Java \345\206\205\345\255\230\346\250\241\345\236\213\357\274\210Java Memory Model\357\274\211\343\200\213.pdf" differ diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\206\205\345\255\230\346\250\241\345\236\213\357\274\210Java Memory Model\357\274\211/\347\233\270\345\205\263\351\223\276\346\216\245.txt" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\206\205\345\255\230\346\250\241\345\236\213\357\274\210Java Memory Model\357\274\211/\347\233\270\345\205\263\351\223\276\346\216\245.txt" new file mode 100644 index 0000000..4329d01 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\344\272\214\350\212\202 Java \345\206\205\345\255\230\346\250\241\345\236\213\357\274\210Java Memory Model\357\274\211/\347\233\270\345\205\263\351\223\276\346\216\245.txt" @@ -0,0 +1,14 @@ +Concurrency JSR-166 Interest Site +http://g.oswego.edu/dl/concurrency-interest/ + +Memory Barriers and JVM Concurrency +https://www.infoq.com/articles/memory_barriers_jvm_concurrency + +JSR +https://github.com/mercyblitz/jsr + +Bill Pugh +http://www.cs.umd.edu/~pugh/ + +Atomic Access +https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html \ No newline at end of file diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\345\233\233\350\212\202 JVM \345\271\266\345\217\221\345\256\236\347\216\260/2006 - Eliminating synchronization-related atomic operations with biased locking and bulk rebiasing .pdf" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\345\233\233\350\212\202 JVM \345\271\266\345\217\221\345\256\236\347\216\260/2006 - Eliminating synchronization-related atomic operations with biased locking and bulk rebiasing .pdf" new file mode 100644 index 0000000..4b4ad90 Binary files /dev/null and "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\345\233\233\350\212\202 JVM \345\271\266\345\217\221\345\256\236\347\216\260/2006 - Eliminating synchronization-related atomic operations with biased locking and bulk rebiasing .pdf" differ diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\345\233\233\350\212\202 JVM \345\271\266\345\217\221\345\256\236\347\216\260/Biased Locking in HotSpot - Dave - 2006.pdf" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\345\233\233\350\212\202 JVM \345\271\266\345\217\221\345\256\236\347\216\260/Biased Locking in HotSpot - Dave - 2006.pdf" new file mode 100644 index 0000000..eca38e3 Binary files /dev/null and "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\345\233\233\350\212\202 JVM \345\271\266\345\217\221\345\256\236\347\216\260/Biased Locking in HotSpot - Dave - 2006.pdf" differ diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\345\233\233\350\212\202 JVM \345\271\266\345\217\221\345\256\236\347\216\260/README.md" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\345\233\233\350\212\202 JVM \345\271\266\345\217\221\345\256\236\347\216\260/README.md" new file mode 100644 index 0000000..016b446 --- /dev/null +++ "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\345\233\233\350\212\202 JVM \345\271\266\345\217\221\345\256\236\347\216\260/README.md" @@ -0,0 +1,546 @@ +# `JVM 并发实现 + + + +## Java 线程 - java.lang.Thread + + + +### 预备知识 + +- C++ Basic +- JNI - Java Native Interface +- POSIX Thread + + + +### java.lang.Thread API 定义 + +#### 基本操作 + +##### 创建 - `new Thread()` + +Thread 对象 new 实际普通的 Java 对象创建,不涉及 JVM 或者 OS 线程创建和启动 + +JNI 类型:`jobject` + +##### 启动 - `Thread#start()` + + `Thread#start()` 引导线程启动,不一定马上启动(非阻塞),终究会 `Thread#run()` 方法(回调) + + `Thread#start()` 方法定义: + +```java +public synchronized void start() { // 线程安全 + ... + group.add(this); // 将当前线程添加到所在 ThreadGroup + ... + try { + start0(); // Native 方法 + } + ... +} + +private native void start0(); // JNI Java 调用 JVM 方法 +``` + + + +Java 类名称: `java.lang.Thread ` + +```java +public +class Thread implements Runnable { + /* Make sure registerNatives is the first thing does. */ + private static native void registerNatives(); + static { + registerNatives(); + } + ... +} +``` + +JNI 方法名称(C 函数): + +```c++ +JNIEXPORT void JNICALL +Java_java_lang_Thread_registerNatives(JNIEnv *env, jclass cls) +{ + (*env)->RegisterNatives(env, cls, methods, ARRAY_LENGTH(methods)); +} +``` + + + +java.lang.Thread native 方法的映射表: + +```c++ +static JNINativeMethod methods[] = { + {"start0", "()V", (void *)&JVM_StartThread}, + {"stop0", "(" OBJ ")V", (void *)&JVM_StopThread}, + {"isAlive", "()Z", (void *)&JVM_IsThreadAlive} + ... +}; +``` + + + +方法签名:`java.lang.Thread#start0()` + +Native 方法:`JVM_StartThread` + +```c++ +/* + * java.lang.Thread + */ +JNIEXPORT void JNICALL +JVM_StartThread(JNIEnv *env, jobject thread); +``` + +> 方法声明位置:`/jdk/src/share/javavm/export/jvm.h` + +实现入口: + +```c++ +JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread)) +... +{ + jlong size = + java_lang_Thread::stackSize(JNIHandles::resolve_non_null(jthread)); + ... + size_t sz = size > 0 ? (size_t) size : 0; + native_thread = new JavaThread(&thread_entry, sz); + ... +} +``` + +`native_thread` 创建了 `JavaThread` 类型对象,第一个构造参数 `&thread_entry`,即函数指针(引用函数 `thread_entry`): + +```c++ +static void thread_entry(JavaThread* thread, TRAPS) { + HandleMark hm(THREAD); + Handle obj(THREAD, thread->threadObj()); // 1 + JavaValue result(T_VOID); + JavaCalls::call_virtual(&result, // 2 + obj, // 3 + KlassHandle(THREAD, SystemDictionary::Thread_klass()), // 4 + vmSymbols::run_method_name(), // 5 + vmSymbols::void_method_signature(), // 6 + THREAD); +} +``` + +1. `thread->threadObject()` 返回了 Java 代码创建 `java.lang.Thread` 对象 +2. 调用 JVM C++ 对象虚拟方法(多态) +3. obj `java.lang.Thread` 对象包装 +4. java.lang.Thread 类对象 +5. `java.lang.Thread#run()` 方法名称 +6. `void` 方法签名 + +综上所述,`thread_entry` 方法执行目的是要执行 `java.lang.Thread` 对象的`run()` 方法 + + + +分析 `JavaThread::JavaThread` 构造器: + +```c++ +JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) + ... +{ + ... + set_entry_point(entry_point); // 设置 thread_entry 函数到当前对象 + ... + os::create_thread(this, thr_type, stack_sz); + ... +} +``` + +第一个构造参数 `entry_point` 是 `ThreadFunction`, `entry_point` 实际指向函数 - `thread_entry`,`thread_entry` 函数会被 `JavaThread` 对象作为成员变量保存,接下来执行 `os::create_thread(this, thr_type, stack_sz);` 方法,以 Linux 实现为例: + +```java +bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) { + assert(thread->osthread() == NULL, "caller responsible"); + + // Allocate the OSThread object + OSThread* osthread = new OSThread(NULL, NULL); + if (osthread == NULL) { + return false; + } + + // set the correct thread state + osthread->set_thread_type(thr_type); + + // Initial state is ALLOCATED but not INITIALIZED + osthread->set_state(ALLOCATED); + + thread->set_osthread(osthread); + + // init thread attributes + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + ... + pthread_t tid; + int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread); + + pthread_attr_destroy(&attr); + + ... + return true; +} +``` + +`java.lang.Thread#start0()` -> JVM JNI -> POSIX Thread `pthread_create` + +`java_start` 函数就是实际 JVM 执行操作: + +```c++ +static void *java_start(Thread *thread) { + ... + // call one more level start routine + thread->run(); + + return 0; +} +``` + +参数 `thread` 实际为 `JavaThread` 对象,`thread->run()` 调用实际是 `JavaThread::run()` 方法的执行: + +```c++ +void JavaThread::run() { + ... + thread_main_inner(); + // Note, thread is no longer valid at this point! +} + +void JavaThread::thread_main_inner() { + ... + if (!this->has_pending_exception() && + !java_lang_Thread::is_stillborn(this->threadObj())) { + { + ResourceMark rm(this); + this->set_native_thread_name(this->get_thread_name()); + } + HandleMark hm(this); + this->entry_point()(this, this); + } + + DTRACE_THREAD_PROBE(stop, this); + + this->exit(false); + delete this; +} +``` + +`this->entry_point` 是 `JavaThread` 成员变量,指向 `thread_entry` 函数: + +```sequence +Thread.start0() -> JVM_StartThread : JVM Native 调用 +JVM_StartThread -> new JavaThread() : 创建一个 JavaThread() 对象 +new JavaThread() -> os_create_thread() : 创建线程(OS 相关的) +os_create_thread() -> pthread_create() : 创建 POSIX Thread +pthread_create() -> java_start() : 线程启动并回调 java_start() +java_start() -> JavaThread_run() : 调用 JavaThread run() 方法 +JavaThread_run() -> thread_main_inner() : 内部调用 +thread_main_inner() -> entry_point() : entry_point 指向 thread_entry() +thread_entry() -> java.lang.Thread.run() : 回调 Java Thread run() 方法 +``` + +当 `java.lang.Thread#start()` 方法调用完成,JVM 所创建的`JavaThread`对象就移除: `delete this` + + + +##### 完成 - `Thread#join()` + +`java.lang.Thread#join()` 底层使用 `java.lang.Object#wait(long)` 方法实现: + +```java + public final synchronized void join(long millis) + throws InterruptedException { + ... + if (millis == 0) { + while (isAlive()) { + wait(0); + } + } + ... + } +``` + + `java.lang.Object#wait(long)` 方法: + +```java +public class Object { + + private static native void registerNatives(); + static { + registerNatives(); + } + ... + public final native void wait(long timeoutMillis) throws InterruptedException; + ... +} +``` + +Object Native 实现:jdk/src/share/native/java/lang/Object.c + +```c++ +static JNINativeMethod methods[] = { + {"hashCode", "()I", (void *)&JVM_IHashCode}, + {"wait", "(J)V", (void *)&JVM_MonitorWait}, + {"notify", "()V", (void *)&JVM_MonitorNotify}, + {"notifyAll", "()V", (void *)&JVM_MonitorNotifyAll}, + {"clone", "()Ljava/lang/Object;", (void *)&JVM_Clone}, +}; +``` + +`wait(long)` 方法映射 `JVM_MonitorWait`: + +```c++ +JVM_ENTRY(void, JVM_MonitorWait(JNIEnv* env, jobject handle, jlong ms)) + JVMWrapper("JVM_MonitorWait"); + Handle obj(THREAD, JNIHandles::resolve_non_null(handle)); + JavaThreadInObjectWaitState jtiows(thread, ms != 0); + if (JvmtiExport::should_post_monitor_wait()) { + JvmtiExport::post_monitor_wait((JavaThread *)THREAD, (oop)obj(), ms); + } + ObjectSynchronizer::wait(obj, ms, CHECK); // 1 +JVM_END +``` + +1. ObjectSynchronizer::wait(obj, ms, CHECK): + +```c++ + +``` + + + +wait() 方法执行前提,当前线程获得锁(synchronized) + +T1-> 获得锁(synchronized ) -> wait() -> 释放锁 + +T2(等待获得锁) + +T3 + + + +`Object#wait()` + + + +Object -> Object Monitor -> WaitSet + +```java +Object monitor = new Object(); +synchronized(monitor) { + if(true){ + monitor.wait(); // monitor WaitSet {T1 -> T2 -> T3} + } +} + +synchronized(monitor) { + if(true){ + monitor.notify(); // T4 monitor WaitSet pop() T1 + } +} +``` + + + +WaitSet 属于 ObjectMonitor 成员: + +```c++ +class ObjectMonitor { + ... + protected: + ObjectWaiter * volatile _WaitSet; // LL of threads wait()ing on the monitor +} +``` + +_WaitSet 是 `ObjectWaiter` 类型对象,属于双向队列节点: + +```c++ +class ObjectWaiter : public StackObj { + public: + ... + ObjectWaiter * volatile _next; // 下一个节点(Waiter) + ObjectWaiter * volatile _prev; // 上一个节点(Waiter) + Thread* _thread; + jlong _notifier_tid; + ParkEvent * _event; + volatile int _notified ; + volatile TStates TState ; + Sorted _Sorted ; // List placement disposition + bool _active ; // Contention monitoring is enabled + public: + ObjectWaiter(Thread* thread); + + void wait_reenter_begin(ObjectMonitor *mon); + void wait_reenter_end(ObjectMonitor *mon); +}; +``` + +JVM `ObjectWaiter` 类似于 Java AQS `AbstractQueuedSynchronizer.Node` + + + + `ObjectWaiter` 属于 CLH (双向)队列节点(自旋锁) + +```c++ +void Thread::SpinAcquire (volatile int * adr, const char * LockName) { + ... + for (;;) { + while (*adr != 0) { + ++ctr ; + if ((ctr & 0xFFF) == 0 || !os::is_MP()) { + if (Yields > 5) { + // Consider using a simple NakedSleep() instead. + // Then SpinAcquire could be called by non-JVM threads + Thread::current()->_ParkEvent->park(1) ; + } else { + os::NakedYield() ; + ++Yields ; + } + } else { + SpinPause() ; + } + } + if (Atomic::cmpxchg (1, adr, 0) == 0) return ; + } + ... +} +``` + + + +`AbstractQueuedSynchronizer.Node` 属于 CLH 变种(双向)队列节点(阻塞): + +```java + private final boolean parkAndCheckInterrupt() { + LockSupport.park(this); + return Thread.interrupted(); + } +``` + + + +JVM `ParkEvent->park` 以及 JDK `LockSupport.park(this)` 底层同为 `pthread_cond_wait` 函数。 + +相反, + +JVM `ParkEvent->unpark` 以及 JDK `LockSupport.unpark(this)` 底层同为 `pthread_cond_singal` 函数。 + + + +WaitSet + +N1(T1) + + + +自旋锁(Spin Lock) + +CLH 队列 + +- 原生 - JVM ParkEvent(自旋) +- 变种 - JDK AQS Node(阻塞) + - LockSupport#park() + + + +当前 Thread + +Part Event (CLH 队列) + + + +`jdk.internal.misc.Unsafe#park`: + +```java +public final class Unsafe { + + private static native void registerNatives(); + static { + registerNatives(); + } + + public native void park(boolean isAbsolute, long time) +} + +``` + +`hotspot/src/share/vm/prims/unsafe.cpp`: + +```c++ +UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time)) + UnsafeWrapper("Unsafe_Park"); + EventThreadPark event; +... + JavaThreadParkedState jtps(thread, time != 0); + thread->parker()->park(isAbsolute != 0, time); +... +UNSAFE_END +``` + +实际执行的代码:`thread->parker()->park`, 当前线程关联的 `Parker` 对象(由 parker() 方法返回) + + + +结论: + +- `java.lang.Object#wait(long)` + - `JVM_MonitorWait` + - `ObjectSynchronizer::wait` + - `Self->_ParkEvent->park ()` + - `os::PlatformEvent::park()` + - OS `pthread_cond_wait` +- `Unsafe#park(boolean,long)` + - JVM Native + - JVM `Parker::park` + - OS `pthread_cond_wait` +- `Unsafe#unpark()` + - JVM Native + - JVM `Parker::unpark` + - OS `pthread_cond_singal` + + + +T1 park -> 释放锁 + +T2 获得锁 -> park + +T3 获得锁 + + + +T main -> T1.unpark + + + + + + + + + +- 中止 - `Thread#interrupt()` +- 休眠 - `Thread#sleep(long)` +- 让出 - `Thread#yield()` +- 停止 - ~~Thread#stop()~~ + + + + + +### JNI 接口定义 + + + + + + + + + diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\345\233\233\350\212\202 JVM \345\271\266\345\217\221\345\256\236\347\216\260/Synchronization - Christian Wimmer - 2008.pdf" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\345\233\233\350\212\202 JVM \345\271\266\345\217\221\345\256\236\347\216\260/Synchronization - Christian Wimmer - 2008.pdf" new file mode 100644 index 0000000..4b14ca7 Binary files /dev/null and "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\345\233\233\350\212\202 JVM \345\271\266\345\217\221\345\256\236\347\216\260/Synchronization - Christian Wimmer - 2008.pdf" differ diff --git "a/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\345\233\233\350\212\202 JVM \345\271\266\345\217\221\345\256\236\347\216\260/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\345\233\233\346\234\237 \347\254\254\345\233\233\350\212\202\343\200\212JVM \345\271\266\345\217\221\345\256\236\347\216\260\343\200\213.pdf" "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\345\233\233\350\212\202 JVM \345\271\266\345\217\221\345\256\236\347\216\260/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\345\233\233\346\234\237 \347\254\254\345\233\233\350\212\202\343\200\212JVM \345\271\266\345\217\221\345\256\236\347\216\260\343\200\213.pdf" new file mode 100644 index 0000000..d94e575 Binary files /dev/null and "b/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215/\347\254\254\345\233\233\346\234\237/\347\254\254\345\233\233\350\212\202 JVM \345\271\266\345\217\221\345\256\236\347\216\260/\343\200\214\344\270\200\345\205\245 Java \346\267\261\344\274\274\346\265\267 \343\200\215\347\263\273\345\210\227 \347\254\254\345\233\233\346\234\237 \347\254\254\345\233\233\350\212\202\343\200\212JVM \345\271\266\345\217\221\345\256\236\347\216\260\343\200\213.pdf" differ