百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT知识 > 正文

Java多线程终极指南:从基础到高级应用

liuian 2025-05-27 15:53 51 浏览

一、多线程基础概念

1.1 进程与线程的区别

对比维度 进程(Process) 线程(Thread) 定义 操作系统资源分配的基本单位 CPU调度的基本单位 内存空间 独立内存空间 共享所属进程的内存空间 通信方式 进程间通信(IPC)较复杂 可直接读写共享变量 创建开销 大(需要分配独立资源) 小(共享进程资源) 稳定性 一个进程崩溃不影响其他进程 一个线程崩溃可能导致整个进程退出

进程(Process)

在Java中,进程是操作系统资源分配的基本单位,具有独立的内存空间。每个Java应用程序运行时都至少有一个进程。进程特点包括:

  • 独立性:拥有独立的地址空间、数据栈等
  • 资源开销大:创建和销毁需要较多系统资源
  • 通信复杂:进程间通信(IPC)需要特殊机制(如管道、套接字等)

线程(Thread)

线程是Java并发编程的基本执行单元,是进程内的一个独立执行流。特点包括:

  • 共享进程资源:同一进程内的线程共享堆内存和方法区
  • 轻量级:创建和切换开销远小于进程
  • 通信简单:可通过共享变量直接通信
  • Java通过java.lang.Thread类和Runnable接口实现多线程

进程 vs 线程:餐厅比喻

想象一家餐厅:

  • 进程就像整个餐厅,有独立的厨房(内存)、收银台(资源)
  • 线程就像餐厅里的服务员,多个服务员共享同一个厨房和收银台

1.2 为什么需要多线程

  1. 提高CPU利用率:当线程I/O阻塞时,其他线程可以继续使用CPU
  2. 更快的响应:GUI程序使用单独线程处理用户输入
  3. 简化建模:每个线程处理单一任务,代码更清晰
  4. 多核优势:现代CPU多核心可真正并行执行线程

日常例子:浏览器同时下载多个文件(每个下载任务一个线程),同时还能响应用户操作(UI线程)。

二、Java线程创建与管理

2.1 创建线程的三种方式

方式1:继承Thread类

// 自定义线程类
class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("线程执行: " + Thread.currentThread().getName());
    }
}

public class ThreadDemo {
    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start();  // 启动线程
    }
}

方式2:实现Runnable接口

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("Runnable线程: " + Thread.currentThread().getName());
    }
}

public class RunnableDemo {
    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable());
        thread.start();
    }
}

方式3:使用Callable和Future(可获取返回值)

import java.util.concurrent.*;

class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        Thread.sleep(1000);
        return "Callable结果";
    }
}

public class CallableDemo {
    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<String> future = executor.submit(new MyCallable());
        
        System.out.println("等待结果...");
        String result = future.get();  // 阻塞直到获取结果
        System.out.println("获取结果: " + result);
        
        executor.shutdown();
    }
}

2.2 三种创建方式对比

对比点 继承Thread类 实现Runnable接口 实现Callable接口 返回值 无 无 有 异常处理 只能在run()内处理 只能在run()内处理 可以通过Future获取 单继承限制 受限于Java单继承 不受限 不受限 线程池支持 不支持 支持 支持 适用场景 简单线程任务 推荐方式 需要返回结果的场景

建议:优先选择实现Runnable接口或Callable接口的方式,避免继承的局限性。

三、线程生命周期与状态转换

3.1 线程的6种状态

Java线程在生命周期中有6种状态(定义在Thread.State枚举中):

  1. **NEW(新建)**:线程被创建但尚未启动
  2. **RUNNABLE(可运行)**:线程正在JVM中执行或等待操作系统资源
  3. **BLOCKED(阻塞)**:等待监视器锁(进入synchronized块)
  4. **WAITING(等待)**:无限期等待其他线程执行特定操作(如wait())
  5. **TIMED_WAITING(计时等待)**:有限时间等待(如sleep())
  6. **TERMINATED(终止)**:线程执行完毕

3.2 状态转换图

NEW ---start()---> RUNNABLE
RUNNABLE ---获取锁---> BLOCKED
RUNNABLE ---wait()---> WAITING
RUNNABLE ---sleep()---> TIMED_WAITING
WAITING ---notify()---> RUNNABLE
TIMED_WAITING ---时间到---> RUNNABLE
RUNNABLE ---run()结束---> TERMINATED

代码示例观察状态

public class ThreadStateDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        
        System.out.println("新建状态: " + thread.getState());  // NEW
        
        thread.start();
        System.out.println("启动后状态: " + thread.getState());  // RUNNABLE
        
        Thread.sleep(100);
        System.out.println("sleep时状态: " + thread.getState());  // TIMED_WAITING
        
        thread.join();
        System.out.println("结束后状态: " + thread.getState());  // TERMINATED
    }
}

四、线程同步与锁机制

4.1 同步问题的产生

概念:当多个线程访问共享资源时,由于线程调度的不确定性,可能导致:

  • 竞态条件(Race Condition):执行结果依赖于线程执行的时序
  • 内存可见性问题:线程对共享变量的修改对其他线程不可见
  • 指令重排序:编译器和处理器优化导致的执行顺序改变

例如:这就像你和室友共用一个冰箱:

  • 你看到最后一瓶可乐(检查条件)
  • 你伸手去拿(执行操作)
  • 同时你室友也伸手
  • 结果要么:1) 你俩各拿到半瓶 2) 系统崩溃 3) 可乐凭空消失

经典问题:银行取款问题

class BankAccount {
    private int balance = 1000;
    
    public void withdraw(int amount) {
        if (balance >= amount) {
            try {
                Thread.sleep(10);  // 模拟处理时间
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            balance -= amount;
            System.out.println(Thread.currentThread().getName() + "取款" + amount + ",余额: " + balance);
        } else {
            System.out.println("余额不足");
        }
    }
}

public class BankDemo {
    public static void main(String[] args) {
        BankAccount account = new BankAccount();
        
        // 两个线程同时取款
        new Thread(() -> account.withdraw(800), "线程1").start();
        new Thread(() -> account.withdraw(800), "线程2").start();
    }
}

输出可能

线程1取款800,余额: 200
线程2取款800,余额: -600

4.2 同步解决方案

方案1:synchronized关键字

特性

  • 内置锁(Intrinsic Lock)/监视器锁(Monitor Lock)
  • 保证原子性(atomicity)和可见性(visibility)
  • 可重入性(Reentrancy):线程可以重复获取已持有的锁
  • 方法级和代码块级两种使用方式

流程

  1. 线程到达同步代码:"我要进这个房间"
  2. JVM门神:"请出示你的锁对象身份证"
  3. 如果没人占用:"请进,记得出来时敲门"
  4. 如果已被占用:"门口排队,别踢门!"
public class house {
    private final Object lock = new Object();
    
    public void use() {
        synchronized(lock) {  // 获取锁
            // 临界区代码
            System.out.println("正在使用中...");
        }  // 释放锁
    }
    
    public synchronized void clean() {  // 方法级同步
        System.out.println("保洁阿姨工作中");
    }
}

方案2:ReentrantLock

特性

  • 可重入
  • 可中断(lockInterruptibly)
  • 尝试获取锁(tryLock)
  • 公平/非公平模式
import java.util.concurrent.locks.ReentrantLock;

class BankAccount {
    private final ReentrantLock lock = new ReentrantLock();
    private int balance = 1000;
    
    public void withdraw(int amount) {
        lock.lock();  // 加锁
        try {
            if (balance >= amount) {
                Thread.sleep(10);
                balance -= amount;
                System.out.println(Thread.currentThread().getName() + "取款" + amount + ",余额: " + balance);
            } else {
                System.out.println("余额不足");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();  // 确保释放锁
        }
    }
}

4.3 synchronized与ReentrantLock对比

对比点 synchronized ReentrantLock 实现机制 JVM层面实现 JDK代码实现 锁获取方式 自动获取释放 需要手动lock/unlock 灵活性 相对不灵活 可尝试获取锁、定时锁、公平锁等 性能 优化后性能接近 高竞争下性能更好 中断响应 不支持 支持lockInterruptibly() 条件队列 单一 可创建多个Condition 适用场景 简单同步需求 复杂同步控制

五、线程间通信

5.1 wait/notify机制

生产者-消费者模型

class MessageQueue {
    private String message;
    private boolean empty = true;
    
    public synchronized String take() {
        while (empty) {
            try {
                wait();  // 等待消息
            } catch (InterruptedException e) {}
        }
        empty = true;
        notifyAll();  // 通知生产者
        return message;
    }
    
    public synchronized void put(String message) {
        while (!empty) {
            try {
                wait();  // 等待消费
            } catch (InterruptedException e) {}
        }
        empty = false;
        this.message = message;
        notifyAll();  // 通知消费者
    }
}

public class ProducerConsumerDemo {
    public static void main(String[] args) {
        MessageQueue queue = new MessageQueue();
        
        // 生产者
        new Thread(() -> {
            String[] messages = {"消息1", "消息2", "消息3"};
            for (String msg : messages) {
                queue.put(msg);
                System.out.println("生产: " + msg);
            }
        }).start();
        
        // 消费者
        new Thread(() -> {
            for (int i = 0; i < 3; i++) {
                String msg = queue.take();
                System.out.println("消费: " + msg);
            }
        }).start();
    }
}

5.2 Condition接口

import java.util.concurrent.locks.*;

class BoundedBuffer {
    final Lock lock = new ReentrantLock();
    final Condition notFull = lock.newCondition();
    final Condition notEmpty = lock.newCondition();
    
    final Object[] items = new Object[100];
    int putptr, takeptr, count;
    
    public void put(Object x) throws InterruptedException {
        lock.lock();
        try {
            while (count == items.length)
                notFull.await();  // 等待不满
            items[putptr] = x;
            if (++putptr == items.length) putptr = 0;
            ++count;
            notEmpty.signal();  // 通知不空
        } finally {
            lock.unlock();
        }
    }
    
    public Object take() throws InterruptedException {
        lock.lock();
        try {
            while (count == 0)
                notEmpty.await();  // 等待不空
            Object x = items[takeptr];
            if (++takeptr == items.length) takeptr = 0;
            --count;
            notFull.signal();  // 通知不满
            return x;
        } finally {
            lock.unlock();
        }
    }
}

六、线程池与Executor框架

6.1 为什么使用线程池

  1. 降低资源消耗:重复利用已创建的线程
  2. 提高响应速度:任务到达时线程已存在
  3. 提高线程可管理性:统一分配、调优和监控
  4. 防止资源耗尽:限制最大线程数

6.2 线程池核心参数

参数 说明 corePoolSize 核心线程数,即使空闲也不会被回收 maximumPoolSize 最大线程数,当工作队列满时创建新线程直到达到此数量 keepAliveTime 非核心线程空闲存活时间 unit 存活时间单位 workQueue 工作队列,保存等待执行的任务 threadFactory 线程工厂,用于创建新线程 handler 拒绝策略,当线程池和工作队列都满时如何处理新任务

6.3 四种常见线程池

// 1. 固定大小线程池
ExecutorService fixedPool = Executors.newFixedThreadPool(5);

// 2. 单线程池(保证顺序执行)
ExecutorService singleThread = Executors.newSingleThreadExecutor();

// 3. 缓存线程池(自动扩容)
ExecutorService cachedPool = Executors.newCachedThreadPool();

// 4. 定时任务线程池
ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(3);

6.4 自定义线程池示例

public class ThreadPoolDemo {
    public static void main(String[] args) {
        // 自定义线程池
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
            2,  // 核心线程数
            4,  // 最大线程数
            60, // 空闲时间
            TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(2),  // 任务队列容量2
            new ThreadPoolExecutor.CallerRunsPolicy()  // 拒绝策略
        );
        
        // 提交10个任务
        for (int i = 1; i <= 10; i++) {
            final int taskId = i;
            executor.execute(() -> {
                System.out.println("执行任务 " + taskId + ",线程: " + Thread.currentThread().getName());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        
        executor.shutdown();
    }
}

6.5 线程池拒绝策略

策略 行为 AbortPolicy 默认策略,直接抛出RejectedExecutionException CallerRunsPolicy 用调用者所在线程来执行任务 DiscardPolicy 直接丢弃任务,不做任何处理 DiscardOldestPolicy 丢弃队列中最旧的任务,然后尝试提交当前任务

七、高级并发工具类

7.1 CountDownLatch

应用场景:多个线程等待直到所有前置操作完成

public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(3);  // 需要计数3次
        
        new Thread(() -> {
            System.out.println("任务1完成");
            latch.countDown();  // 计数减1
        }).start();
        
        new Thread(() -> {
            System.out.println("任务2完成");
            latch.countDown();
        }).start();
        
        new Thread(() -> {
            System.out.println("任务3完成");
            latch.countDown();
        }).start();
        
        latch.await();  // 等待计数归零
        System.out.println("所有任务完成,继续主线程");
    }
}

7.2 CyclicBarrier

应用场景:一组线程互相等待到达屏障点

public class CyclicBarrierDemo {
    public static void main(String[] args) {
        CyclicBarrier barrier = new CyclicBarrier(3, () -> {
            System.out.println("所有线程到达屏障,执行屏障动作");
        });
        
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "到达屏障");
                try {
                    barrier.await();  // 等待其他线程
                } catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "继续执行");
            }).start();
        }
    }
}

7.3 Semaphore

应用场景:控制同时访问特定资源的线程数量

public class SemaphoreDemo {
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(3);  // 允许3个线程同时访问
        
        for (int i = 1; i <= 10; i++) {
            new Thread(() -> {
                try {
                    semaphore.acquire();  // 获取许可
                    System.out.println(Thread.currentThread().getName() + "获得许可,执行中...");
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    System.out.println(Thread.currentThread().getName() + "释放许可");
                    semaphore.release();  // 释放许可
                }
            }, "线程" + i).start();
        }
    }
}

7.4 并发工具对比

工具类 作用 关键方法 可重用性 CountDownLatch 一个或多个线程等待其他线程完成操作 countDown(), await() 否 CyclicBarrier 一组线程互相等待到达屏障点 await() 是 Semaphore 控制同时访问特定资源的线程数量 acquire(), release() 是 Phaser 更灵活的屏障,可以动态注册和注销参与方 arrive(), awaitAdvance() 是

八、原子变量与CAS

8.1 原子操作类

Java提供了一系列原子变量类,如AtomicInteger, AtomicLong, AtomicReference等。

public class AtomicDemo {
    public static void main(String[] args) throws InterruptedException {
        AtomicInteger counter = new AtomicInteger(0);
        
        Runnable task = () -> {
            for (int i = 0; i < 1000; i++) {
                counter.incrementAndGet();  // 原子递增
            }
        };
        
        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);
        
        t1.start();
        t2.start();
        
        t1.join();
        t2.join();
        
        System.out.println("最终计数: " + counter.get());  // 总是2000
    }
}

8.2 CAS原理

CAS(Compare And Swap)是原子变量的实现原理,包含三个操作数:

  • 内存位置(V)
  • 预期原值(A)
  • 新值(B)

当且仅当V的值等于A时,处理器才会用B更新V的值,否则不执行更新。

ABA问题:虽然值还是A,但可能已经被修改过又改回来了。解决方案:使用AtomicStampedReference带版本号。

九、并发集合类

9.1 常用并发集合

接口 非线程安全实现 线程安全实现 List ArrayList CopyOnWriteArrayList Set HashSet CopyOnWriteArraySet, ConcurrentSkipListSet Map HashMap ConcurrentHashMap, ConcurrentSkipListMap Queue LinkedList ArrayBlockingQueue, LinkedBlockingQueue Deque ArrayDeque LinkedBlockingDeque

9.2 ConcurrentHashMap示例

public class ConcurrentHashMapDemo {
    public static void main(String[] args) {
        ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
        
        // 多个线程并发写入
        ExecutorService executor = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 10; i++) {
            final int taskId = i;
            executor.execute(() -> {
                for (int j = 0; j < 100; j++) {
                    String key = "key-" + taskId + "-" + j;
                    map.put(key, j);
                }
            });
        }
        
        executor.shutdown();
        try {
            executor.awaitTermination(1, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        System.out.println("Map大小: " + map.size());
    }
}

9.3 CopyOnWriteArrayList示例

public class CopyOnWriteDemo {
    public static void main(String[] args) {
        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
        
        // 一个线程迭代
        new Thread(() -> {
            list.add("A");
            list.add("B");
            Iterator<String> it = list.iterator();
            while (it.hasNext()) {
                System.out.println("迭代: " + it.next());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        
        // 另一个线程修改
        new Thread(() -> {
            try {
                Thread.sleep(500);
                list.add("C");
                System.out.println("添加了C");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

十、Java内存模型(JMM)与happens-before

10.1 JMM核心概念

Java内存模型定义了线程如何与内存交互,主要解决以下问题:

  1. 原子性:基本读写操作是原子的
  2. 可见性:一个线程修改对另一个线程可见
  3. 有序性:防止指令重排序

10.2 happens-before原则

  1. 程序顺序规则:同一线程中的操作,前面的happens-before后面的
  2. 锁规则:解锁happens-before后续加锁
  3. volatile规则:写happens-before后续读
  4. 线程启动规则:线程start()happens-before它的任何操作
  5. 线程终止规则:线程的所有操作happens-before它的终止检测
  6. 中断规则:调用interrupt()happens-before检测到中断
  7. 终结器规则:对象构造happens-before它的finalize()
  8. 传递性:A hb B,B hb C => A hb C

10.3 volatile关键字

public class VolatileDemo {
    private volatile boolean running = true;
    
    public void stop() {
        running = false;
    }
    
    public void run() {
        while (running) {
            // 工作代码
        }
        System.out.println("线程停止");
    }
    
    public static void main(String[] args) throws InterruptedException {
        VolatileDemo demo = new VolatileDemo();
        new Thread(demo::run).start();
        Thread.sleep(1000);
        demo.stop();
    }
}

十一、实战案例分析

11.1 高性能计数器

public class HighPerformanceCounter {
    private final AtomicLong counter = new AtomicLong(0);
    private final LongAdder fastCounter = new LongAdder();
    
    // 简单原子计数器
    public void incrementAtomic() {
        counter.incrementAndGet();
    }
    
    // 高并发优化计数器
    public void incrementAdder() {
        fastCounter.increment();
    }
    
    public long getAtomicCount() {
        return counter.get();
    }
    
    public long getAdderCount() {
        return fastCounter.sum();
    }
    
    public static void main(String[] args) throws InterruptedException {
        HighPerformanceCounter counter = new HighPerformanceCounter();
        
        ExecutorService executor = Executors.newFixedThreadPool(8);
        long start = System.currentTimeMillis();
        
        // 测试AtomicLong性能
        for (int i = 0; i < 1000000; i++) {
            executor.execute(counter::incrementAtomic);
        }
        
        executor.shutdown();
        executor.awaitTermination(1, TimeUnit.MINUTES);
        long atomicTime = System.currentTimeMillis() - start;
        
        executor = Executors.newFixedThreadPool(8);
        start = System.currentTimeMillis();
        
        // 测试LongAdder性能
        for (int i = 0; i < 1000000; i++) {
            executor.execute(counter::incrementAdder);
        }
        
        executor.shutdown();
        executor.awaitTermination(1, TimeUnit.MINUTES);
        long adderTime = System.currentTimeMillis() - start;
        
        System.out.println("AtomicLong结果: " + counter.getAtomicCount() + ", 耗时: " + atomicTime + "ms");
        System.out.println("LongAdder结果: " + counter.getAdderCount() + ", 耗时: " + adderTime + "ms");
    }
}

11.2 限流器实现

public class RateLimiter {
    private final Semaphore semaphore;
    private final int maxPermits;
    private final long period;
    private ScheduledExecutorService scheduler;
    
    public RateLimiter(int permits, long period, TimeUnit unit) {
        this.semaphore = new Semaphore(permits);
        this.maxPermits = permits;
        this.period = unit.toMillis(period);
        this.scheduler = Executors.newScheduledThreadPool(1);
        
        scheduler.scheduleAtFixedRate(() -> {
            int current = semaphore.availablePermits();
            if (current < maxPermits) {
                semaphore.release(maxPermits - current);
            }
        }, 0, this.period, TimeUnit.MILLISECONDS);
    }
    
    public boolean tryAcquire() {
        return semaphore.tryAcquire();
    }
    
    public void acquire() throws InterruptedException {
        semaphore.acquire();
    }
    
    public void shutdown() {
        scheduler.shutdown();
    }
    
    public static void main(String[] args) throws InterruptedException {
        // 每秒最多5个请求
        RateLimiter limiter = new RateLimiter(5, 1, TimeUnit.SECONDS);
        
        // 模拟10个请求
        for (int i = 1; i <= 10; i++) {
            if (limiter.tryAcquire()) {
                System.out.println("处理请求 " + i);
            } else {
                System.out.println("限流请求 " + i);
            }
            Thread.sleep(100);
        }
        
        limiter.shutdown();
    }
}

十二、常见问题与最佳实践

12.1 多线程常见问题

  1. 死锁:多个线程互相等待对方释放锁
  2. 避免方法:按固定顺序获取锁,使用tryLock()设置超时
  3. 活锁:线程不断改变状态但无法继续执行
  4. 避免方法:引入随机性,如随机等待时间
  5. 线程饥饿:某些线程长期得不到执行
  6. 解决方法:使用公平锁,合理设置线程优先级

12.2 最佳实践

  1. 尽量使用高层并发工具:如线程池、并发集合
  2. 优先使用不可变对象:避免同步问题
  3. 缩小同步范围:只同步必要的代码块
  4. 避免过早优化:先保证正确性,再考虑性能
  5. 考虑使用并行流:Java 8+的parallelStream()
  6. 合理设置线程池大小
  7. CPU密集型:CPU核心数+1
  8. IO密集型:CPU核心数 × (1 + 平均等待时间/平均计算时间)

12.3 性能调优建议

  1. 减少锁竞争
  2. 缩小同步块
  3. 使用读写锁(ReentrantReadWriteLock)
  4. 使用分段锁(如ConcurrentHashMap)
  5. 避免上下文切换
  6. 合理设置线程数
  7. 使用协程(如Quasar库)
  8. 使用无锁数据结构
  9. Atomic类
  10. LongAdder
  11. ConcurrentLinkedQueue

总结

Java多线程编程是Java高级开发的核心技能之一。本文从基础概念到高级应用,全面介绍了Java多线程的各个方面:

  1. 线程创建与生命周期管理
  2. 同步机制与锁优化
  3. 线程间通信方式
  4. 线程池与Executor框架
  5. 高级并发工具类
  6. 原子变量与CAS
  7. 并发集合类
  8. Java内存模型
  9. 实战案例与最佳实践

Java 多线程像一群疯跑的小怪兽,协调好就齐力通关,没控制住,程序直接被它们折腾得 “脑震荡”!

★ 收藏转发的人,2024年必暴富!——来自一位贫穷但真诚的博主。


相关推荐

教你把多个视频合并成一个视频的方法

一.情况介绍当你有一个m3u8文件和一个目录,目录中有连续的视频片段,这些片段可以连成一段完整的视频。m3u8文件打开后像这样:m3u8文件,可以理解为播放列表,里面是播放视频片段的顺序。视频片段像这...

零代码编程:用kimichat合并一个文件夹下的多个文件

一个文件夹里面有很多个srt字幕文件,如何借助kimichat来自动批量合并呢?在kimichat对话框中输入提示词:你是一个Python编程专家,完成如下的编程任务:这个文件夹:D:\downloa...

Java APT_java APT 生成代码

JavaAPT(AnnotationProcessingTool)是一种在Java编译阶段处理注解的工具。APT会在编译阶段扫描源代码中的注解,并根据这些注解生成代码、资源文件或其他输出,...

Unit Runtime:一键运行 AI 生成的代码,或许将成为你的复制 + 粘贴神器

在我们构建了UnitMesh架构之后,以及对应的demo之后,便着手于实现UnitMesh架构。于是,我们就继续开始UnitRuntime,以用于直接运行AI生成的代码。PS:...

挣脱臃肿的枷锁:为什么说Vert.x是Java开发者手中的一柄利剑?

如果你是一名Java开发者,那么你的职业生涯几乎无法避开Spring。它如同一位德高望重的老国王,统治着企业级应用开发的大片疆土。SpringBoot的约定大于配置、SpringCloud的微服务...

五年后,谷歌还在全力以赴发展 Kotlin

作者|FredericLardinois译者|Sambodhi策划|Tina自2017年谷歌I/O全球开发者大会上,谷歌首次宣布将Kotlin(JetBrains开发的Ja...

kotlin和java开发哪个好,优缺点对比

Kotlin和Java都是常见的编程语言,它们有各自的优缺点。Kotlin的优点:简洁:Kotlin程序相对于Java程序更简洁,可以减少代码量。安全:Kotlin在类型系统和空值安全...

移动端架构模式全景解析:从MVC到MVVM,如何选择最佳设计方案?

掌握不同架构模式的精髓,是构建可维护、可测试且高效移动应用的关键。在移动应用开发中,选择合适的软件架构模式对项目的可维护性、可测试性和团队协作效率至关重要。随着应用复杂度的增加,一个良好的架构能够帮助...

颜值非常高的XShell替代工具Termora,不一样的使用体验!

Termora是一款面向开发者和运维人员的跨平台SSH终端与文件管理工具,支持Windows、macOS及Linux系统,通过一体化界面简化远程服务器管理流程。其核心定位是解决多平台环境下远程连接、文...

预处理的底层原理和预处理编译运行异常的解决方案

若文章对您有帮助,欢迎关注程序员小迷。助您在编程路上越走越好![Mac-10.7.1LionIntel-based]Q:预处理到底干了什么事情?A:预处理,顾名思义,预先做的处理。源代码中...

为“架构”再建个模:如何用代码描述软件架构?

在架构治理平台ArchGuard中,为了实现对架构的治理,我们需要代码+模型描述所要处理的内容和数据。所以,在ArchGuard中,我们有了代码的模型、依赖的模型、变更的模型等,剩下的两个...

深度解析:Google Gemma 3n —— 移动优先的轻量多模态大模型

2025年6月,Google正式发布了Gemma3n,这是一款能够在2GB内存环境下运行的轻量级多模态大模型。它延续了Gemma家族的开源基因,同时在架构设计上大幅优化,目标是让...

比分网开发技术栈与功能详解_比分网有哪些

一、核心功能模块一个基本的比分网通常包含以下模块:首页/总览实时比分看板:滚动展示所有正在进行的比赛,包含比分、比赛时间、红黄牌等关键信息。热门赛事/焦点战:突出显示重要的、关注度高的比赛。赛事导航...

设计模式之-生成器_一键生成设计

一、【概念定义】——“分步构建复杂对象,隐藏创建细节”生成器模式(BuilderPattern):一种“分步构建型”创建型设计模式,它将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建...

构建第一个 Kotlin Android 应用_kotlin简介

第一步:安装AndroidStudio(推荐IDE)AndroidStudio是官方推荐的Android开发集成开发环境(IDE),内置对Kotlin的完整支持。1.下载And...