package cn.meowrain;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

public class ThreadSafetyAnalysis {

    // --- 成员变量和静态变量是否线程安全? ---

    // 1. 成员变量 (非静态)
    // 1.1 如果它们没有共享, 则线程安全
    static class MemberVarNotShared {
        private int count = 0; // 成员变量

        public void incrementAndPrint() {
            count++;
            System.out.println(Thread.currentThread().getName() + ": count = " + count);
        }

        public static void demo() throws InterruptedException {
            System.out.println("--- 1.1 成员变量 - 没有共享 (每个线程一个新对象) ---");
            Thread t1 = new Thread(() -> new MemberVarNotShared().incrementAndPrint(), "T1_MemberNotShared");
            Thread t2 = new Thread(() -> new MemberVarNotShared().incrementAndPrint(), "T2_MemberNotShared");
            t1.start();
            t2.start();
            t1.join();
            t2.join();
            // 输出会是 T1: count = 1, T2: count = 1 (顺序不定)
            // 因为每个线程操作的是不同对象的 count 成员变量
        }
    }

    // 1.2 如果它们被共享了
    // 1.2.1 如果只有读操作, 则线程安全
    static class SharedMemberVarReadOnly {
        private final String message = "Hello, World!"; // final 确保了初始化后不可变

        public void printMessage() {
            System.out.println(Thread.currentThread().getName() + ": message = " + message);
        }

        public static void demo() throws InterruptedException {
            System.out.println("\n--- 1.2.1 共享成员变量 - 只有读操作 ---");
            SharedMemberVarReadOnly sharedReader = new SharedMemberVarReadOnly();
            Thread t1 = new Thread(() -> sharedReader.printMessage(), "T1_SharedRead");
            Thread t2 = new Thread(() -> sharedReader.printMessage(), "T2_SharedRead");
            t1.start();
            t2.start();
            t1.join();
            t2.join();
            // 线程安全,因为 message 是 final 且只被读取
        }
    }

    // 1.2.2 如果有读写操作, 则这段代码是临界区, 需要考虑线程安全
    // 1.2.2.a) 非线程安全示例
    static class SharedMemberVarReadWriteUnsafe {
        private int count = 0; // 共享成员变量

        public void increment() {
            count++; // 读-改-写 操作,非原子
        }

        public int getCount() {
            return count;
        }

        public static void demo() throws InterruptedException {
            System.out.println("\n--- 1.2.2.a 共享成员变量 - 读写操作 (不安全) ---");
            SharedMemberVarReadWriteUnsafe unsafeCounter = new SharedMemberVarReadWriteUnsafe();
            int numThreads = 1000;
            CountDownLatch latch = new CountDownLatch(numThreads);
            ExecutorService executor = Executors.newFixedThreadPool(10);

            for (int i = 0; i < numThreads; i++) {
                executor.submit(() -> {
                    unsafeCounter.increment();
                    latch.countDown();
                });
            }
            latch.await();
            executor.shutdown();
            System.out.println("Unsafe counter final count: " + unsafeCounter.getCount() + " (Expected " + numThreads + ", but likely less)");
            // 结果通常会小于 1000,因为 count++ 不是原子操作
        }
    }

    // 1.2.2.b) 线程安全示例 (使用 synchronized)
    static class SharedMemberVarReadWriteSafe {
        private int count = 0; // 共享成员变量

        public synchronized void increment() { // synchronized 保护临界区
            count++;
        }

        public int getCount() {
            return count;
        }

        public static void demo() throws InterruptedException {
            System.out.println("\n--- 1.2.2.b 共享成员变量 - 读写操作 (安全 - synchronized) ---");
            SharedMemberVarReadWriteSafe safeCounter = new SharedMemberVarReadWriteSafe();
            int numThreads = 1000;
            CountDownLatch latch = new CountDownLatch(numThreads);
            ExecutorService executor = Executors.newFixedThreadPool(10);

            for (int i = 0; i < numThreads; i++) {
                executor.submit(() -> {
                    safeCounter.increment();
                    latch.countDown();
                });
            }
            latch.await();
            executor.shutdown();
            System.out.println("Safe counter (synchronized) final count: " + safeCounter.getCount() + " (Expected " + numThreads + ")");
            // 结果会是 1000
        }
    }

    // 2. 静态变量 (总是被共享)
    // 2.1 如果只有读操作, 则线程安全 (同成员变量)
    static class SharedStaticVarReadOnly {
        private static final String STATIC_MESSAGE = "Static Hello!";

        public void printStaticMessage() {
            System.out.println(Thread.currentThread().getName() + ": static message = " + STATIC_MESSAGE);
        }
        public static void demo() throws InterruptedException {
            System.out.println("\n--- 2.1 共享静态变量 - 只有读操作 ---");
            SharedStaticVarReadOnly readerInstance1 = new SharedStaticVarReadOnly();
            SharedStaticVarReadOnly readerInstance2 = new SharedStaticVarReadOnly(); // 即使不同实例,静态变量也是同一个
            Thread t1 = new Thread(() -> readerInstance1.printStaticMessage(), "T1_StaticRead");
            Thread t2 = new Thread(() -> readerInstance2.printStaticMessage(), "T2_StaticRead");
            t1.start();
            t2.start();
            t1.join();
            t2.join();
        }
    }

    // 2.2 如果有读写操作, 则需要考虑线程安全
    // 2.2.a) 非线程安全示例
    static class SharedStaticVarReadWriteUnsafe {
        private static int staticCount = 0;

        public void incrementStatic() {
            staticCount++;
        }
        public static int getStaticCount() {
            return staticCount;
        }
        public static void demo() throws InterruptedException {
            System.out.println("\n--- 2.2.a 共享静态变量 - 读写操作 (不安全) ---");
            // 重置一下计数器,因为它是静态的,会被之前的测试影响(如果在同一个JVM实例中运行多次)
            staticCount = 0;
            SharedStaticVarReadWriteUnsafe unsafeStaticCounter1 = new SharedStaticVarReadWriteUnsafe();
            SharedStaticVarReadWriteUnsafe unsafeStaticCounter2 = new SharedStaticVarReadWriteUnsafe();
            int numThreads = 1000;
            CountDownLatch latch = new CountDownLatch(numThreads);
            ExecutorService executor = Executors.newFixedThreadPool(10);

            for (int i = 0; i < numThreads; i++) {
                executor.submit(() -> {
                    // 随机使用不同实例的方法,但它们操作的是同一个静态变量
                    if (Math.random() > 0.5) {
                        unsafeStaticCounter1.incrementStatic();
                    } else {
                        unsafeStaticCounter2.incrementStatic();
                    }
                    latch.countDown();
                });
            }
            latch.await();
            executor.shutdown();
            System.out.println("Unsafe static counter final count: " + getStaticCount() + " (Expected " + numThreads + ", but likely less)");
        }
    }
    // 2.2.b) 线程安全示例 (使用 AtomicInteger)
    static class SharedStaticVarReadWriteSafe {
        private static AtomicInteger atomicStaticCount = new AtomicInteger(0);

        public void incrementStaticAtomic() {
            atomicStaticCount.incrementAndGet();
        }
        public static int getAtomicStaticCount() {
            return atomicStaticCount.get();
        }
        public static void demo() throws InterruptedException {
            System.out.println("\n--- 2.2.b 共享静态变量 - 读写操作 (安全 - AtomicInteger) ---");
            atomicStaticCount.set(0); // 重置
            SharedStaticVarReadWriteSafe safeStaticCounter1 = new SharedStaticVarReadWriteSafe();
            SharedStaticVarReadWriteSafe safeStaticCounter2 = new SharedStaticVarReadWriteSafe();
            int numThreads = 1000;
            CountDownLatch latch = new CountDownLatch(numThreads);
            ExecutorService executor = Executors.newFixedThreadPool(10);

            for (int i = 0; i < numThreads; i++) {
                executor.submit(() -> {
                    if (Math.random() > 0.5) {
                        safeStaticCounter1.incrementStaticAtomic();
                    } else {
                        safeStaticCounter2.incrementStaticAtomic();
                    }
                    latch.countDown();
                });
            }
            latch.await();
            executor.shutdown();
            System.out.println("Safe static counter (Atomic) final count: " + getAtomicStaticCount() + " (Expected " + numThreads + ")");
        }
    }


    // --- 局部变量是否线程安全? ---

    // 1. 局部变量是线程安全的 (指变量本身,如基本类型或引用)
    static class LocalVarIsThreadSafe {
        public void process() {
            int localPrimitive = 0; // 局部基本类型变量
            String localReference = "start"; // 局部引用变量,指向一个不可变对象

            for (int i = 0; i < 5; i++) {
                localPrimitive++;
                localReference = localReference + "-" + i; // 每次都会创建一个新的String对象
            }
            // 每个线程都有自己的 localPrimitive 和 localReference 副本
            System.out.println(Thread.currentThread().getName() + ": localPrimitive = " + localPrimitive +
                    ", localReference ends with " + localReference.substring(localReference.length()-2));
        }

        public static void demo() throws InterruptedException {
            System.out.println("\n--- 局部变量本身是线程安全的 ---");
            LocalVarIsThreadSafe processor = new LocalVarIsThreadSafe();
            Thread t1 = new Thread(() -> processor.process(), "T1_LocalVar");
            Thread t2 = new Thread(() -> processor.process(), "T2_LocalVar");
            t1.start();
            t2.start();
            t1.join();
            t2.join();
            // 每个线程都能正确完成自己的计算,输出都是 localPrimitive = 5, localReference ends with -4
        }
    }

    // 2. 但局部变量引用的对象则未必
    // 2.1 如果该对象没有逃离方法的作用范围, 它是线程安全的
    static class LocalObjectRefNotEscaped {
        public void processList() {
            List<String> localList = new ArrayList<>(); // 局部变量引用一个只在方法内使用的对象
            for (int i = 0; i < 3; i++) {
                localList.add(Thread.currentThread().getName() + "_val_" + i);
            }
            System.out.println(Thread.currentThread().getName() + ": Local list size = " + localList.size() + ", content: " + localList);
            // localList 没有被返回,没有赋值给成员变量或静态变量,没有传递给其他可能共享它的方法
            // 因此,这个 ArrayList 实例只被当前线程访问,是线程安全的。
        }
        public static void demo() throws InterruptedException {
            System.out.println("\n--- 局部变量引用的对象 - 没有逃离方法范围 ---");
            LocalObjectRefNotEscaped processor = new LocalObjectRefNotEscaped();
            Thread t1 = new Thread(() -> processor.processList(), "T1_LocalObjNoEscape");
            Thread t2 = new Thread(() -> processor.processList(), "T2_LocalObjNoEscape");
            t1.start();
            t2.start();
            t1.join();
            t2.join();
            // 每个线程都有自己的 ArrayList 实例
        }
    }

    // 2.2 如果该对象逃离方法的作用范围, 需要考虑线程安全
    static class LocalObjectRefEscaped {
        // 共享的列表,用于演示对象逃逸后的问题
        private static final List<String> SHARED_LIST_UNSAFE = new ArrayList<>(); // 非线程安全的List
        private static final List<String> SHARED_LIST_SAFE = new Vector<>();   // 线程安全的List (或 Collections.synchronizedList)

        public void addToListUnsafe(String value) {
            StringBuilder localSb = new StringBuilder(value); // 局部变量,引用的对象是新的
            // ... 做一些操作 ...
            localSb.append("_processed_by_").append(Thread.currentThread().getName());
            SHARED_LIST_UNSAFE.add(localSb.toString()); // 对象 (toString()的结果) 逃逸到了共享列表
            // 如果多个线程同时操作 SHARED_LIST_UNSAFE (非线程安全),可能出问题。
            // 这里的 'localSb.toString()' 产生的新String是不可变的,所以添加到List里是安全的。
            // 更危险的逃逸是把 localSb 本身 (如果它是可变的且被后续修改) 或一个可变集合给外部。
        }

        public void addToListSafe(String value) {
            StringBuilder localSb = new StringBuilder(value);
            localSb.append("_processed_by_").append(Thread.currentThread().getName());
            SHARED_LIST_SAFE.add(localSb.toString()); // Vector是线程安全的
        }

        // 演示一个更典型的“逃逸”导致问题的场景
        public List<String> createAndReturnList() {
            List<String> localList = new ArrayList<>(); // 局部创建
            localList.add("item_from_" + Thread.currentThread().getName());
            return localList; // localList 逃逸了!
        }

        // 如果把 createAndReturnList 返回的 list 赋值给一个共享变量,并且多个线程修改它,就会有问题
        public static List<String> globallyAccessibleList; // 用于演示逃逸后的共享

        public static void demo() throws InterruptedException {
            System.out.println("\n--- 局部变量引用的对象 - 逃离方法范围 ---");
            LocalObjectRefEscaped processor = new LocalObjectRefEscaped();
            int numThreads = 100;
            CountDownLatch latchUnsafe = new CountDownLatch(numThreads);
            CountDownLatch latchSafe = new CountDownLatch(numThreads);
            CountDownLatch latchEscaped = new CountDownLatch(numThreads);
            ExecutorService executor = Executors.newFixedThreadPool(10);

            System.out.println("--- 2.2.a 逃逸到非线程安全共享集合 (ArrayList add本身非线程安全) ---");
            SHARED_LIST_UNSAFE.clear();
            for (int i = 0; i < numThreads; i++) {
                final int val = i;
                executor.submit(() -> {
                    processor.addToListUnsafe("unsafe_item_" + val);
                    latchUnsafe.countDown();
                });
            }
            latchUnsafe.await();
            // ArrayList 的 add 操作本身如果并发可能导致内部数组扩容问题等,或者丢失元素。
            // 虽然我们添加的是String (不可变),但ArrayList本身状态的修改不是线程安全的。
            System.out.println("SHARED_LIST_UNSAFE size: " + SHARED_LIST_UNSAFE.size() + " (Expected " + numThreads + ", may vary or throw CMEs in extreme cases)");


            System.out.println("\n--- 2.2.b 逃逸到线程安全共享集合 ---");
            SHARED_LIST_SAFE.clear();
            for (int i = 0; i < numThreads; i++) {
                final int val = i;
                executor.submit(() -> {
                    processor.addToListSafe("safe_item_" + val);
                    latchSafe.countDown();
                });
            }
            latchSafe.await();
            System.out.println("SHARED_LIST_SAFE size: " + SHARED_LIST_SAFE.size() + " (Expected " + numThreads + ")");

            System.out.println("\n--- 2.2.c 局部对象通过返回值逃逸,并被共享和修改 (不安全) ---");
            // 这个例子稍微复杂一点,演示真正的"对象逃逸后被不安全地共享"
            // 我们让每个线程创建一个 List,然后尝试把这个 list "合并"到一个全局的 list 中。
            // 如果全局 list 是 ArrayList,并且多个线程同时 addAll,就会出问题。
            globallyAccessibleList = new ArrayList<>(); // 非线程安全的全局 list
            for (int i = 0; i < numThreads; i++) {
                executor.submit(() -> {
                    List<String> returnedList = processor.createAndReturnList(); // localList 逃逸了
                    // 现在多个线程可能同时修改 globallyAccessibleList
                    // globallyAccessibleList.addAll(returnedList); // 这是不安全的
                    synchronized (LocalObjectRefEscaped.class) { // 必须加锁保护共享的 globallyAccessibleList
                        globallyAccessibleList.addAll(returnedList);
                    }
                    latchEscaped.countDown();
                });
            }
            latchEscaped.await();
            System.out.println("GloballyAccessibleList (escaped) size: " + globallyAccessibleList.size() + " (Expected " + numThreads + ")");


            executor.shutdown();
        }
    }


    public static void main(String[] args) throws InterruptedException {
        MemberVarNotShared.demo();
        SharedMemberVarReadOnly.demo();
        SharedMemberVarReadWriteUnsafe.demo();
        SharedMemberVarReadWriteSafe.demo();

        SharedStaticVarReadOnly.demo();
        SharedStaticVarReadWriteUnsafe.demo();
        SharedStaticVarReadWriteSafe.demo();

        LocalVarIsThreadSafe.demo();
        LocalObjectRefNotEscaped.demo();
        LocalObjectRefEscaped.demo();

        System.out.println("\n--- All Demos Completed ---");
    }
}