+ * Subclasses of {@code Thread} should override this method.
+ *
+ * @see #start()
+ */
+ @Override
+ public void run() {
+ super.run();
+ try {
+ for (; ; ) {
+ if (this.isInterrupted()) {
+ throw new InterruptedException("线程中断!");
+ }
+
+ for (int i = 0; i < 10000; i++) {
+ String a = "" + Math.random();
+ }
+ Box.list1.add("生产数据A");
+ System.out.println("list1 size=" + Box.list1.size());
+ }
+ } catch (Exception exception) {
+ exception.printStackTrace();
+ }
+
+ try {
+ while (true) {
+ if (this.isInterrupted()) {
+ throw new InterruptedException("线程中断!");
+ }
+
+ for (int i = 0; i < 10000; i++) {
+ String a = "" + Math.random();
+ }
+
+ Box.list2.add("生产数据B");
+ System.out.println("list2 size=" + Box.list2.size());
+ }
+ } catch (Exception exception) {
+ exception.printStackTrace();
+ }
+ }
+}
diff --git a/multithreading_init/src/main/java/thead/thread_9/Test1.java b/multithreading_init/src/main/java/thead/thread_9/Test1.java
new file mode 100644
index 0000000..02c4c97
--- /dev/null
+++ b/multithreading_init/src/main/java/thead/thread_9/Test1.java
@@ -0,0 +1,31 @@
+package thead.thread_9;
+
+import tools.Box;
+
+public class Test1 {
+ public static void main(String[] args) {
+ try {
+ MyThread thread = new MyThread();
+ thread.start();
+
+ boolean list1IsInterrupted = false;
+ boolean list2IsInterrupted = false;
+
+ while (thread.isAlive()) {
+ if (Box.list1.size() > 500 && !list1IsInterrupted) {
+ thread.interrupt();
+ list1IsInterrupted = true;
+ }
+
+ if (Box.list2.size() > 500 && !list2IsInterrupted) {
+ thread.interrupt();
+ list2IsInterrupted = true;
+ }
+
+ Thread.sleep(50);
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/multithreading_init/src/main/java/thread_1/safe0/SafeCounter.java b/multithreading_init/src/main/java/thread_1/safe0/SafeCounter.java
new file mode 100644
index 0000000..76b2918
--- /dev/null
+++ b/multithreading_init/src/main/java/thread_1/safe0/SafeCounter.java
@@ -0,0 +1,31 @@
+package thread_1.safe0;
+
+import lombok.Getter;
+
+@Getter
+public class SafeCounter {
+ private static Integer count = 0;
+
+ // 使用 synchronized 关键字
+ public static void main(String[] args) throws InterruptedException {
+ Thread[] threads = new Thread[1000];
+ for (int i = 0; i < 1000; i++) {
+ threads[i] = new Thread(() -> {
+ for (int j = 0; j < 1000; j++) {
+ synchronized ("") {
+ count++;
+ }
+ }
+ });
+ threads[i].start();
+ }
+
+ // 等待所有线程完成
+ for (int i = 0; i < 1000; i++) {
+ threads[i].join();
+ }
+
+ // 输出最终计数值
+ System.out.println("Count: " + count); // 结果应该等于 1000000
+ }
+}
diff --git a/multithreading_init/src/main/java/thread_1/safe0/UnsafeCounter.java b/multithreading_init/src/main/java/thread_1/safe0/UnsafeCounter.java
new file mode 100644
index 0000000..db356be
--- /dev/null
+++ b/multithreading_init/src/main/java/thread_1/safe0/UnsafeCounter.java
@@ -0,0 +1,29 @@
+package thread_1.safe0;
+
+import lombok.Getter;
+
+@Getter
+public class UnsafeCounter {
+ private static Integer count = 0;
+
+ public static void main(String[] args) throws InterruptedException {
+ // 创建 1000 个线程并进行计数
+ Thread[] threads = new Thread[1000];
+ for (int i = 0; i < 1000; i++) {
+ threads[i] = new Thread(() -> {
+ for (int j = 0; j < 1000; j++) {
+ count++;
+ }
+ });
+ threads[i].start();
+ }
+
+ // 等待所有线程完成
+ for (int i = 0; i < 1000; i++) {
+ threads[i].join();
+ }
+
+ // 输出最终计数值
+ System.out.println("Count: " + count); // 结果应该等于 1000000
+ }
+}
diff --git a/multithreading_init/src/main/java/thread_1/safe1/SafeCounter.java b/multithreading_init/src/main/java/thread_1/safe1/SafeCounter.java
new file mode 100644
index 0000000..755834d
--- /dev/null
+++ b/multithreading_init/src/main/java/thread_1/safe1/SafeCounter.java
@@ -0,0 +1,37 @@
+package thread_1.safe1;
+
+import lombok.Getter;
+
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+@Getter
+public class SafeCounter {
+
+ private static final Lock lock = new ReentrantLock();
+
+ private static Integer count = 0;
+
+ public static void main(String[] args) throws InterruptedException {
+ // 创建 1000 个线程并进行计数
+ Thread[] threads = new Thread[1000];
+ for (int i = 0; i < 1000; i++) {
+ threads[i] = new Thread(() -> {
+ for (int j = 0; j < 1000; j++) {
+ lock.lock();
+ count++;
+ lock.unlock();
+ }
+ });
+ threads[i].start();
+ }
+
+ // 等待所有线程完成
+ for (int i = 0; i < 1000; i++) {
+ threads[i].join();
+ }
+
+ // 输出最终计数值
+ System.out.println("Count: " + count); // 结果应该等于 1000000
+ }
+}
diff --git a/multithreading_init/src/main/java/thread_1/safe2/AtomicSafe.java b/multithreading_init/src/main/java/thread_1/safe2/AtomicSafe.java
new file mode 100644
index 0000000..92fd31a
--- /dev/null
+++ b/multithreading_init/src/main/java/thread_1/safe2/AtomicSafe.java
@@ -0,0 +1,27 @@
+package thread_1.safe2;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class AtomicSafe {
+ private static final AtomicInteger count = new AtomicInteger(0);
+
+ public static void main(String[] args) throws InterruptedException {
+ // 创建 1000 个线程并进行计数
+ Thread[] threads = new Thread[1000];
+ for (int i = 0; i < 1000; i++) {
+ threads[i] = new Thread(() -> {
+ for (int j = 0; j < 1000; j++) {
+ count.incrementAndGet();
+ }
+ });
+ threads[i].start();
+ }
+
+ // 等待所有线程完成
+ for (Thread t : threads) {
+ t.join();
+ }
+
+ System.out.println(count.get());
+ }
+}
diff --git a/multithreading_init/src/main/java/thread_1/safe3/Run.java b/multithreading_init/src/main/java/thread_1/safe3/Run.java
new file mode 100644
index 0000000..8ffb4c3
--- /dev/null
+++ b/multithreading_init/src/main/java/thread_1/safe3/Run.java
@@ -0,0 +1,60 @@
+package thread_1.safe3;
+
+public class Run {
+ public static void main(String[] args) {
+ PrivateNum privateNum1 = new PrivateNum();
+ PrivateNum privateNum2 = new PrivateNum();
+
+ new ThreadA(privateNum1).start();
+ new ThreadB(privateNum2).start();
+ }
+
+ /**
+ * 在这个方法中前面是否加 synchronized 对结果都没有影响,因为资源不是共享的
+ */
+ public static class PrivateNum {
+ synchronized public void testMethod() {
+ try {
+ System.out.println(Thread.currentThread().getName() + " 开始 " + System.currentTimeMillis());
+ Thread.sleep(3000);
+ System.out.println(Thread.currentThread().getName() + " 结束 " + System.currentTimeMillis());
+ } catch (Exception exception) {
+ exception.printStackTrace();
+ }
+ }
+ }
+
+ // 线程A
+ public static class ThreadA extends Thread {
+
+ private final PrivateNum privateNum;
+
+ public ThreadA(PrivateNum privateNum) {
+ super();
+ this.privateNum = privateNum;
+ }
+
+ @Override
+ public void run() {
+ super.run();
+ privateNum.testMethod();
+ }
+ }
+
+ // 线程B
+ public static class ThreadB extends Thread {
+
+ private final PrivateNum privateNum;
+
+ public ThreadB(PrivateNum privateNum) {
+ super();
+ this.privateNum = privateNum;
+ }
+
+ @Override
+ public void run() {
+ super.run();
+ privateNum.testMethod();
+ }
+ }
+}
diff --git a/multithreading_init/src/main/java/thread_1/safe4/SynchronizedMethodLocakObject.java b/multithreading_init/src/main/java/thread_1/safe4/SynchronizedMethodLocakObject.java
new file mode 100644
index 0000000..b1d8b87
--- /dev/null
+++ b/multithreading_init/src/main/java/thread_1/safe4/SynchronizedMethodLocakObject.java
@@ -0,0 +1,63 @@
+package thread_1.safe4;
+
+public class SynchronizedMethodLocakObject {
+
+ public static void main(String[] args) {
+ MyObject myObject = new MyObject();
+
+ ThreadA threadA = new ThreadA(myObject);
+ threadA.setName("ThreadA");
+ threadA.start();
+
+ ThreadB threadB = new ThreadB(myObject);
+ threadB.setName("ThreadB");
+ threadB.start();
+ }
+
+ // 对象
+ public static class MyObject {
+ synchronized public void methodA() {
+ try {
+ System.out.println(Thread.currentThread().getName() + " 开始 " + System.currentTimeMillis());
+ Thread.sleep(1000);
+ System.out.println(Thread.currentThread().getName() + " 结束 " + System.currentTimeMillis());
+ } catch (Exception exception) {
+ exception.printStackTrace();
+ }
+ }
+ }
+
+ // 线程A
+ public static class ThreadA extends Thread {
+
+ private final MyObject myObject;
+
+ public ThreadA(MyObject myObject) {
+ super();
+ this.myObject = myObject;
+ }
+
+ @Override
+ public void run() {
+ super.run();
+ myObject.methodA();
+ }
+ }
+
+ // 线程B
+ public static class ThreadB extends Thread {
+
+ private final MyObject myObject;
+
+ public ThreadB(MyObject myObject) {
+ super();
+ this.myObject = myObject;
+ }
+
+ @Override
+ public void run() {
+ super.run();
+ myObject.methodA();
+ }
+ }
+}
diff --git a/multithreading_init/src/main/java/thread_1/safe4/SynchronizedMethodLocakObject2.java b/multithreading_init/src/main/java/thread_1/safe4/SynchronizedMethodLocakObject2.java
new file mode 100644
index 0000000..a2b4748
--- /dev/null
+++ b/multithreading_init/src/main/java/thread_1/safe4/SynchronizedMethodLocakObject2.java
@@ -0,0 +1,83 @@
+package thread_1.safe4;
+
+public class SynchronizedMethodLocakObject2 {
+
+ public static void main(String[] args) {
+ MyObject myObject = new MyObject();
+
+ ThreadA threadA = new ThreadA(myObject);
+ threadA.setName("ThreadA");
+
+ ThreadB threadB = new ThreadB(myObject);
+ threadB.setName("ThreadB");
+
+ threadA.start();
+ threadB.start();
+ }
+
+ // 测试对象
+ public static class MyObject {
+
+ /**
+ * 测试方法A
+ */
+ synchronized public void methodA() {
+ try {
+ System.out.println(Thread.currentThread().getName() + " 开始 " + System.currentTimeMillis());
+ Thread.sleep(1000);
+ System.out.println(Thread.currentThread().getName() + " 结束 " + System.currentTimeMillis());
+ } catch (Exception exception) {
+ exception.printStackTrace();
+ }
+ }
+
+ /**
+ * 测试方法B
+ * 如果不加synchronized,整个程序是异步执行的
+ * 如果加synchronized,整个程序是同步执行的
+ */
+ synchronized public void methodB() {
+ try {
+ System.out.println(Thread.currentThread().getName() + " 开始 " + System.currentTimeMillis());
+ Thread.sleep(1000);
+ System.out.println(Thread.currentThread().getName() + " 结束 " + System.currentTimeMillis());
+ } catch (Exception exception) {
+ exception.printStackTrace();
+ }
+ }
+ }
+
+ // 线程A
+ public static class ThreadA extends Thread {
+
+ private final MyObject myObject;
+
+ public ThreadA(MyObject myObject) {
+ super();
+ this.myObject = myObject;
+ }
+
+ @Override
+ public void run() {
+ super.run();
+ myObject.methodA();
+ }
+ }
+
+ // 线程B
+ public static class ThreadB extends Thread {
+
+ private final MyObject myObject;
+
+ public ThreadB(MyObject myObject) {
+ super();
+ this.myObject = myObject;
+ }
+
+ @Override
+ public void run() {
+ super.run();
+ myObject.methodB();
+ }
+ }
+}
diff --git a/multithreading_init/src/main/java/thread_1/safe5/DirtyReadExample.java b/multithreading_init/src/main/java/thread_1/safe5/DirtyReadExample.java
new file mode 100644
index 0000000..1cbdaa7
--- /dev/null
+++ b/multithreading_init/src/main/java/thread_1/safe5/DirtyReadExample.java
@@ -0,0 +1,42 @@
+package thread_1.safe5;
+
+// 在多线程编程中,synchronized 关键字可以确保一个线程在执行某个方法时,其他线程无法同时访问被同步的方法,从而避免多个线程同时修改共享数据的问题。
+// 脏读(Dirty Read)指的是一个线程读取到另一个线程还未提交的修改数据,这种数据在另一个线程最终提交或者回滚后可能会发生变化,因此是不可靠的。
+public class DirtyReadExample {
+
+ private Integer sharedValue = 0; // 共享变量
+
+ // 假设我们有一个多线程程序,其中多个线程同时对共享变量进行操作,未对共享变量进行适当的同步,就可能会发生脏读。
+ // 例如,线程 A 读取了线程 B 未提交的修改,或者线程 B 在 A 修改时正在读取数据,导致读取到的数据不一致。
+ public static void main(String[] args) {
+ DirtyReadExample example = new DirtyReadExample();
+ Thread threadA = new Thread(example::threadA);
+ Thread threadB = new Thread(example::threadB);
+
+ threadA.start();
+ threadB.start();
+ }
+
+ // 线程A方法:修改共享变量
+ synchronized public void threadA() {
+ sharedValue = 100;
+ System.out.println("ThreadA 修改 sharedValue 为: " + sharedValue);
+ try {
+ Thread.sleep(2000); // 模拟长时间操作
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ sharedValue = 200;
+ System.out.println("ThreadA 修改 sharedValue 为: " + sharedValue);
+ }
+
+ // 线程B方法:读取共享变量
+ synchronized public void threadB() {
+ try {
+ Thread.sleep(1000); // 确保线程A先运行
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ System.out.println("ThreadB 读取 sharedValue: " + sharedValue); // 读取共享变量
+ }
+}
diff --git a/multithreading_init/src/main/java/thread_1/safe6/SynchronizedReentrantExample.java b/multithreading_init/src/main/java/thread_1/safe6/SynchronizedReentrantExample.java
new file mode 100644
index 0000000..8be15df
--- /dev/null
+++ b/multithreading_init/src/main/java/thread_1/safe6/SynchronizedReentrantExample.java
@@ -0,0 +1,40 @@
+package thread_1.safe6;
+
+/**
+ * sychronized 锁重入指的是一个线程在获得一个锁之后,可以再次进入该锁(即再次获取锁)而不会发生死锁。
+ * 这是因为 sychronized 锁是可重入的(reentrant)。
+ * 当一个线程获取锁并进入一个同步方法时,它的锁计数会增加。
+ * 该线程在执行另一个同步方法时,锁计数继续增加,表示它可以再次进入同步方法。
+ * 只有当线程释放锁时,锁计数才会递减,最终锁计数为 0 时,锁才会被释放。
+ */
+public class SynchronizedReentrantExample {
+
+ public static void main(String[] args) {
+ SynchronizedReentrantExample example = new SynchronizedReentrantExample();
+
+ // 创建一个线程来调用 method1
+ Thread thread = new Thread(example::method1);
+ thread.start();
+ }
+
+ // 这个方法是同步的,任何线程都只能一个接着一个访问它
+ public synchronized void method1() {
+ System.out.println("In method1.");
+
+ // 在 method1 中调用 method2,这是对同一个锁的重入
+ method2();
+ }
+
+ // 这个方法也是同步的,线程会在这里等待直到获得锁
+ public synchronized void method2() {
+ System.out.println("In method2.");
+
+ // 在 method2 中调用 method3,这是对同一个锁的重入
+ method3();
+ }
+
+ // 这个方法也是同步的,继续重入锁
+ public synchronized void method3() {
+ System.out.println("In method3.");
+ }
+}
diff --git a/multithreading_init/src/main/java/thread_1/safe7/Counter.java b/multithreading_init/src/main/java/thread_1/safe7/Counter.java
new file mode 100644
index 0000000..f1f154e
--- /dev/null
+++ b/multithreading_init/src/main/java/thread_1/safe7/Counter.java
@@ -0,0 +1,24 @@
+package thread_1.safe7;
+
+import lombok.Getter;
+
+@Getter
+public class Counter {
+ private final Object lock1 = new Object();
+ private final Object lock2 = new Object();
+ private int count1 = 0;
+ private int count2 = 0;
+
+ public void incrementCount1() {
+ synchronized (lock1) {
+ count1++;
+ }
+ }
+
+ public void incrementCount2() {
+ synchronized (lock2) {
+ count2++;
+ }
+ }
+
+}
diff --git a/multithreading_init/src/main/java/thread_1/safe8/Counter.java b/multithreading_init/src/main/java/thread_1/safe8/Counter.java
new file mode 100644
index 0000000..f536937
--- /dev/null
+++ b/multithreading_init/src/main/java/thread_1/safe8/Counter.java
@@ -0,0 +1,36 @@
+package thread_1.safe8;
+
+import lombok.Getter;
+
+public class Counter {
+ @Getter
+ private static int count = 0;
+
+ // 静态同步方法
+ public synchronized static void increment() {
+ count++;
+ }
+
+ public static void main(String[] args) throws InterruptedException {
+ // 创建多个线程调用静态同步方法
+ Thread t1 = new Thread(() -> {
+ for (int i = 0; i < 1000; i++) {
+ Counter.increment(); // 调用静态同步方法
+ }
+ });
+
+ Thread t2 = new Thread(() -> {
+ for (int i = 0; i < 1000; i++) {
+ Counter.increment(); // 调用静态同步方法
+ }
+ });
+
+ t1.start();
+ t2.start();
+
+ t1.join();
+ t2.join();
+
+ System.out.println("Final count: " + Counter.getCount());
+ }
+}
diff --git a/multithreading_init/src/main/java/thread_1/safe9/AtomicIntegerTest.java b/multithreading_init/src/main/java/thread_1/safe9/AtomicIntegerTest.java
new file mode 100644
index 0000000..d5beaf2
--- /dev/null
+++ b/multithreading_init/src/main/java/thread_1/safe9/AtomicIntegerTest.java
@@ -0,0 +1,56 @@
+package thread_1.safe9;
+
+import java.util.concurrent.ConcurrentSkipListMap;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class AtomicIntegerTest {
+ public static void main(String[] args) {
+ MyThread myThread = new MyThread();
+
+ Thread thread1 = new Thread(myThread);
+ Thread thread2 = new Thread(myThread);
+ Thread thread3 = new Thread(myThread);
+ Thread thread4 = new Thread(myThread);
+ Thread thread5 = new Thread(myThread);
+ Thread thread6 = new Thread(myThread);
+ Thread thread7 = new Thread(myThread);
+ Thread thread8 = new Thread(myThread);
+ Thread thread9 = new Thread(myThread);
+ Thread thread10 = new Thread(myThread);
+
+ thread1.start();
+ thread2.start();
+ thread3.start();
+ thread4.start();
+ thread5.start();
+ thread6.start();
+ thread7.start();
+ thread8.start();
+ thread9.start();
+ thread10.start();
+
+ ConcurrentSkipListMap