多线程编程深度解析:Java与Python框架实战指南

一、多线程基础概念回顾

多线程编程是现代软件开发的核心技能,允许程序同时执行多个任务,提高CPU利用率和系统吞吐量。但不同语言对多线程的支持差异显著:

  • Java:基于JVM,原生支持多线程,线程调度由操作系统管理
  • Python:受GIL(全局解释器锁)限制,多线程在CPU密集型任务中受限,更适合IO密集型场景

二、Java多线程框架详解

1. 原生线程模型(Thread/Runnable)

java 复制代码
// 基础用法
public class BasicThread {
    public static void main(String[] args) {
        // 方式1:继承Thread
        Thread t1 = new Thread(() -> {
            System.out.println("线程1执行: " + Thread.currentThread().getName());
        });
        
        // 方式2:实现Runnable(推荐,解耦任务与线程)
        Runnable task = () -> {
            System.out.println("线程2执行: " + Thread.currentThread().getName());
        };
        
        t1.start();
        new Thread(task).start();
    }
}

特点:最基础,但线程创建销毁开销大,不适合高并发场景。


2. Executor框架(线程池)

java 复制代码
import java.util.concurrent.*;
import java.util.List;
import java.util.ArrayList;

public class ExecutorDemo {
    public static void main(String[] args) throws Exception {
        // 创建线程池
        ExecutorService executor = new ThreadPoolExecutor(
            5,                      // 核心线程数
            10,                     // 最大线程数
            60L,                    // 空闲线程存活时间
            TimeUnit.SECONDS,       // 时间单位
            new LinkedBlockingQueue<>(100), // 任务队列
            new ThreadFactory() {   // 线程工厂(自定义线程名)
                private int count = 0;
                @Override
                public Thread newThread(Runnable r) {
                    return new Thread(r, "custom-thread-" + ++count);
                }
            },
            new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
        );
        
        // 提交任务
        List<Future<Integer>> futures = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            final int taskId = i;
            Future<Integer> future = executor.submit(() -> {
                Thread.sleep(100);
                return taskId * taskId;
            });
            futures.add(future);
        }
        
        // 获取结果
        for (Future<Integer> future : futures) {
            System.out.println("结果: " + future.get());
        }
        
        executor.shutdown();
    }
}

Executors工厂方法对比

方法 核心特点 适用场景 风险
newFixedThreadPool(n) 固定线程数,无界队列 负载稳定的任务 队列无限增长导致OOM
newCachedThreadPool() 线程数无上限,60秒回收 短异步小任务 线程数爆炸
newSingleThreadExecutor() 单线程顺序执行 需要保证顺序 同Fixed,无界队列风险
newScheduledThreadPool(n) 支持定时/周期任务 定时任务 注意任务执行时间重叠
newWorkStealingPool() ForkJoinPool,工作窃取 分治算法 任务需支持拆分

3. Fork/Join框架

java 复制代码
import java.util.concurrent.*;
import java.util.Random;

public class ForkJoinDemo {
    // 计算数组总和(分治算法)
    static class SumTask extends RecursiveTask<Long> {
        private static final int THRESHOLD = 10000;
        private long[] array;
        private int start, end;
        
        SumTask(long[] array, int start, int end) {
            this.array = array;
            this.start = start;
            this.end = end;
        }
        
        @Override
        protected Long compute() {
            if (end - start <= THRESHOLD) {
                // 直接计算
                long sum = 0;
                for (int i = start; i < end; i++) {
                    sum += array[i];
                }
                return sum;
            }
            
            // 拆分任务
            int mid = (start + end) / 2;
            SumTask left = new SumTask(array, start, mid);
            SumTask right = new SumTask(array, mid, end);
            
            left.fork();  // 异步执行左任务
            long rightResult = right.compute(); // 同步执行右任务
            long leftResult = left.join();      // 等待左任务结果
            
            return leftResult + rightResult;
        }
    }
    
    public static void main(String[] args) {
        long[] array = new long[1000000];
        Random random = new Random();
        for (int i = 0; i < array.length; i++) {
            array[i] = random.nextInt(100);
        }
        
        ForkJoinPool pool = new ForkJoinPool();
        long result = pool.invoke(new SumTask(array, 0, array.length));
        System.out.println("总和: " + result);
        pool.shutdown();
    }
}

优势 :利用工作窃取算法,适合递归拆分任务;劣势:任务粒度控制不当会导致性能下降。


4. CompletableFuture(异步编程)

java 复制代码
import java.util.concurrent.*;
import java.util.List;
import java.util.stream.Collectors;

public class CompletableFutureDemo {
    private static final ExecutorService executor = Executors.newFixedThreadPool(10);
    
    public static void main(String[] args) throws Exception {
        // 链式异步操作
        CompletableFuture<String> future = CompletableFuture
            .supplyAsync(() -> fetchUserData(1), executor)   // 获取用户
            .thenApply(user -> user + " processed")          // 转换
            .thenCompose(processed -> fetchOrders(processed))  // 异步依赖
            .exceptionally(ex -> "Error: " + ex.getMessage()); // 异常处理
        
        // 并行组合多个异步任务
        List<CompletableFuture<String>> futures = List.of(1, 2, 3).stream()
            .map(id -> CompletableFuture.supplyAsync(() -> fetchUserData(id), executor))
            .collect(Collectors.toList());
        
        // 等待全部完成
        CompletableFuture<Void> allDone = CompletableFuture.allOf(
            futures.toArray(new CompletableFuture[0])
        );
        
        // 获取所有结果
        List<String> results = futures.stream()
            .map(CompletableFuture::join)
            .collect(Collectors.toList());
        
        System.out.println("Results: " + results);
        executor.shutdown();
    }
    
    static String fetchUserData(int id) {
        try { Thread.sleep(100); } catch (InterruptedException e) {}
        return "User-" + id;
    }
    
    static CompletableFuture<String> fetchOrders(String user) {
        return CompletableFuture.supplyAsync(() -> user + "-Orders", executor);
    }
}

5. 响应式编程(Project Reactor / RxJava)

java 复制代码
// Reactor示例(Spring WebFlux底层)
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

public class ReactorDemo {
    public static void main(String[] args) throws Exception {
        // Mono: 0-1个元素
        Mono<String> mono = Mono.fromCallable(() -> {
            Thread.sleep(100);
            return "Hello";
        }).subscribeOn(Schedulers.boundedElastic());
        
        // Flux: 0-N个元素
        Flux<Integer> flux = Flux.range(1, 10)
            .map(i -> i * i)
            .filter(i -> i > 10)
            .publishOn(Schedulers.parallel())  // 切换执行线程
            .doOnNext(i -> System.out.println("Processing " + i + " on " + Thread.currentThread().getName()));
        
        // 背压处理(Backpressure)
        Flux.range(1, 1000)
            .onBackpressureBuffer(100)  // 缓冲区限制
            .subscribeOn(Schedulers.single())
            .subscribe(System.out::println);
        
        // 合并多个流
        Flux<String> merged = Flux.merge(
            fetchFromDB(),
            fetchFromCache()
        );
        
        Thread.sleep(2000); // 等待异步完成
    }
    
    static Flux<String> fetchFromDB() {
        return Flux.just("DB-1", "DB-2").delayElements(java.time.Duration.ofMillis(50));
    }
    
    static Flux<String> fetchFromCache() {
        return Flux.just("Cache-1").delayElements(java.time.Duration.ofMillis(30));
    }
}

三、Python多线程框架详解

1. threading模块(基础多线程)

python 复制代码
import threading
import time
from queue import Queue

class WorkerThread(threading.Thread):
    def __init__(self, queue):
        super().__init__()
        self.queue = queue
        self.daemon = True  # 守护线程,主线程退出时自动结束
    
    def run(self):
        while True:
            task = self.queue.get()
            if task is None:  # 结束信号
                break
            print(f"[{self.name}] 处理任务: {task}")
            time.sleep(0.1)
            self.queue.task_done()

# 使用线程池模式
queue = Queue(maxsize=100)
workers = []
for i in range(5):
    t = WorkerThread(queue)
    t.start()
    workers.append(t)

# 提交任务
for i in range(20):
    queue.put(f"Task-{i}")

queue.join()  # 等待所有任务完成

# 发送结束信号
for _ in workers:
    queue.put(None)
for t in workers:
    t.join()

⚠️ GIL警告:Python的threading在CPU密集型任务中无法利用多核,因为GIL确保同一时刻只有一个线程执行Python字节码。


2. concurrent.futures(高级线程池)

python 复制代码
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor, as_completed
import requests
import time

def fetch_url(url):
    """IO密集型任务:网络请求"""
    try:
        resp = requests.get(url, timeout=5)
        return f"{url}: {resp.status_code}"
    except Exception as e:
        return f"{url}: Error {e}"

urls = [
    "https://api.github.com",
    "https://httpbin.org/get",
    "https://jsonplaceholder.typicode.com/posts/1",
] * 10  # 30个请求

# ThreadPoolExecutor: 适合IO密集型
with ThreadPoolExecutor(max_workers=10) as executor:
    # 方式1:map(保持顺序)
    results = list(executor.map(fetch_url, urls))
    
    # 方式2:submit(谁先完成谁先处理)
    futures = {executor.submit(fetch_url, url): url for url in urls}
    for future in as_completed(futures):
        print(future.result())

# ProcessPoolExecutor: 绕过GIL,适合CPU密集型
def cpu_intensive(n):
    """CPU密集型:计算斐波那契数列"""
    if n <= 1:
        return n
    return cpu_intensive(n-1) + cpu_intensive(n-2)

with ProcessPoolExecutor(max_workers=4) as executor:
    numbers = [30, 32, 34, 35]
    results = list(executor.map(cpu_intensive, numbers))
    print(results)

3. asyncio(异步IO,Python推荐方案)

python 复制代码
import asyncio
import aiohttp
import time
from typing import List

async def fetch_async(session: aiohttp.ClientSession, url: str) -> str:
    """异步HTTP请求"""
    async with session.get(url) as response:
        return f"{url}: {response.status}"

async def main():
    urls = [
        "https://api.github.com",
        "https://httpbin.org/get",
        "https://jsonplaceholder.typicode.com/posts/1",
    ] * 100
    
    # 使用连接池限制并发数
    connector = aiohttp.TCPConnector(limit=50, limit_per_host=10)
    async with aiohttp.ClientSession(connector=connector) as session:
        # 方式1:gather(并发执行,等待全部完成)
        tasks = [fetch_async(session, url) for url in urls]
        results = await asyncio.gather(*tasks, return_exceptions=True)
        
        # 方式2:Semaphore控制并发
        semaphore = asyncio.Semaphore(20)
        
        async def bounded_fetch(url):
            async with semaphore:
                return await fetch_async(session, url)
        
        tasks = [bounded_fetch(url) for url in urls]
        results = await asyncio.gather(*tasks)
        print(f"完成 {len(results)} 个请求")

# 运行事件循环
asyncio.run(main())

asyncio vs threading对比

特性 asyncio threading
并发模型 单线程协程 多线程
适用场景 高并发IO 低并发IO或混合场景
内存占用 极低(协程轻量) 较高(线程栈1MB+)
代码复杂度 需要async/await 同步代码风格
GIL影响 无(单线程)
调试难度 较高(堆栈复杂) 中等

4. multiprocessing(多进程,绕过GIL)

python 复制代码
from multiprocessing import Pool, Manager, cpu_count
from functools import partial
import os

def worker_init():
    """进程初始化(每个子进程只执行一次)"""
    print(f"Worker {os.getpid()} initialized")

def cpu_task(data):
    """CPU密集型任务"""
    result = sum(i * i for i in range(data))
    return result

def parallel_map_reduce(data_list, chunksize=1000):
    """MapReduce风格并行计算"""
    with Pool(
        processes=cpu_count(),
        initializer=worker_init,
        maxtasksperchild=1000  # 防止内存泄漏,处理1000个任务后重启进程
    ) as pool:
        # map: 保持顺序
        results = pool.map(cpu_task, data_list, chunksize=chunksize)
        
        # imap_unordered: 不保证顺序,更快返回
        # for result in pool.imap_unordered(cpu_task, data_list):
        #     print(result)
        
        return results

# 进程间通信
def shared_memory_demo():
    manager = Manager()
    shared_dict = manager.dict()
    shared_list = manager.list()
    lock = manager.Lock()
    
    def update_shared(i):
        with lock:
            shared_dict[i] = i * i
            shared_list.append(i)
    
    with Pool(4) as pool:
        pool.map(update_shared, range(100))
    
    print(f"Dict size: {len(shared_dict)}")
    print(f"List size: {len(shared_list)}")

if __name__ == "__main__":
    data = [100000] * 32
    results = parallel_map_reduce(data)
    print(f"Sum of results: {sum(results)}")

四、框架优劣势对比

框架/技术 语言 优势 劣势 最佳场景
原生Thread Java 简单直观,完全控制 资源开销大,管理复杂 学习演示、少量线程
ExecutorService Java 复用线程,资源可控 配置复杂,需理解队列 大多数并发场景
Fork/Join Java 自动负载均衡,适合分治 任务拆分设计难度大 大数据处理、递归算法
CompletableFuture Java 函数式链式调用,组合灵活 调试困难,异常处理复杂 微服务编排、异步流水线
Reactor/RxJava Java 背压控制,响应式流 学习曲线陡峭 高吞吐量流处理
threading Python 标准库,简单 GIL限制,无法多核 IO密集型低并发
ThreadPoolExecutor Python 接口统一,自动管理 仍受GIL限制 IO密集型中高并发
asyncio Python 单线程高并发,资源占用低 需全链路异步,生态兼容 高并发网络服务
multiprocessing Python 绕过GIL,利用多核 进程间通信开销大 CPU密集型计算

五、性能调优策略

1. 线程池大小调优

Java线程池公式

复制代码
最优线程数 = CPU核心数 * (1 + 等待时间 / 计算时间)

# IO密集型(等待时间长)
线程数 = CPU核数 * 2 或更高(如 Tomcat默认200)

# CPU密集型
线程数 = CPU核数 + 1

Python特殊考虑

  • ThreadPoolExecutor:IO密集型可设置较大(50-100+)
  • ProcessPoolExecutor:通常等于CPU核心数
  • asyncio:理论上无上限,但实际受系统文件描述符限制

2. 队列与缓冲策略

java 复制代码
// Java:有界队列防止OOM
new ArrayBlockingQueue<>(1000);  // 有界,满时触发拒绝策略
new LinkedBlockingQueue<>(1000); // 有界链表队列(优于无界)

// 拒绝策略选择
// AbortPolicy: 直接抛异常(默认,推荐)
// CallerRunsPolicy: 调用者线程执行(降级保护)
// DiscardPolicy: 静默丢弃(不推荐,数据丢失)
// DiscardOldestPolicy: 丢弃最老任务(适合实时性优先)
python 复制代码
# Python:asyncio队列
queue = asyncio.Queue(maxsize=100)  # 有界队列

async def producer():
    for i in range(1000):
        await queue.put(i)  # 满时自动阻塞

async def consumer():
    while True:
        item = await queue.get()
        # 处理...
        queue.task_done()

3. JVM调优参数

bash 复制代码
# 线程栈大小(减少内存占用)
-Xss512k  # 默认1MB,高并发场景可减小

# 垃圾回收器选择(影响线程暂停)
-XX:+UseG1GC  # 低延迟
-XX:MaxGCPauseMillis=200

# 虚拟线程(Java 21+,轻量级线程)
--enable-preview
# 使用:Thread.startVirtualThread(() -> {...})
# 优势:可创建百万级线程,自动调度

4. Python GIL优化

python 复制代码
# 方案1:使用C扩展释放GIL
# numpy等库在C层面释放GIL
import numpy as np
result = np.dot large_matrix1, large_matrix2)  # C层面并行

# 方案2:多进程 + 共享内存
from multiprocessing import shared_memory
shm = shared_memory.SharedMemory(create=True, size=1024)

# 方案3:使用Cython + nogil
# cdef void func() nogil:
#     ...

# 方案4:Python 3.13+ 实验性无GIL构建
# ./configure --disable-gil

六、常见问题与解决方案

问题1:死锁(Deadlock)

现象:线程互相等待对方释放锁,程序卡死。

java 复制代码
// 错误示例:嵌套锁顺序不一致
void transfer(Account a, Account b, int amount) {
    synchronized(a) {           // 线程1获取a
        synchronized(b) {       // 线程1等待b(被线程2持有)
            a.balance -= amount;
            b.balance += amount;
        }
    }
}
// 线程2: synchronized(b) -> synchronized(a) 死锁!

解决方案

java 复制代码
// 方案1:统一加锁顺序(按对象hash排序)
private static final Object tieLock = new Object();

void safeTransfer(Account a, Account b, int amount) {
    int fromHash = System.identityHashCode(a);
    int toHash = System.identityHashCode(b);
    
    if (fromHash < toHash) {
        synchronized(a) { synchronized(b) { doTransfer(a, b, amount); } }
    } else if (fromHash > toHash) {
        synchronized(b) { synchronized(a) { doTransfer(a, b, amount); } }
    } else {
        synchronized(tieLock) {  // hash冲突时使用第三方锁
            synchronized(a) { synchronized(b) { doTransfer(a, b, amount); } }
        }
    }
}

// 方案2:使用tryLock避免永久等待(Java)
boolean acquired = lock.tryLock(1, TimeUnit.SECONDS);
if (acquired) {
    try { /* 执行业务 */ } 
    finally { lock.unlock(); }
}

问题2:线程饥饿(Thread Starvation)

现象:某些线程长期得不到执行机会。

原因

  • 优先级设置不当
  • 锁竞争激烈,某些线程总是抢不到锁
  • 使用非公平锁时,新线程不断插队

解决方案

java 复制代码
// 使用公平锁
ReentrantLock fairLock = new ReentrantLock(true);  // true=公平模式

// 或者使用StampedLock(Java 8+,乐观读)
class Point {
    private double x, y;
    private final StampedLock sl = new StampedLock();
    
    void move(double deltaX, double deltaY) {
        long stamp = sl.writeLock();
        try {
            x += deltaX;
            y += deltaY;
        } finally {
            sl.unlockWrite(stamp);
        }
    }
    
    double distanceFromOrigin() {
        long stamp = sl.tryOptimisticRead();  // 乐观读,无阻塞
        double currentX = x, currentY = y;
        if (!sl.validate(stamp)) {  // 检查是否被修改
            stamp = sl.readLock();  // 升级为悲观读
            try {
                currentX = x;
                currentY = y;
            } finally {
                sl.unlockRead(stamp);
            }
        }
        return Math.sqrt(currentX * currentX + currentY * currentY);
    }
}

问题3:内存泄漏(线程相关)

Java常见原因

  1. ThreadLocal未remove
  2. 线程池任务异常导致线程未回收
  3. 监听器/回调未注销
java 复制代码
// ThreadLocal正确使用
private static final ThreadLocal<SimpleDateFormat> dateFormat = 
    ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));

public void process() {
    try {
        SimpleDateFormat sdf = dateFormat.get();
        // 使用sdf...
    } finally {
        dateFormat.remove();  // 必须清理,防止线程复用时数据混乱
    }
}

// 线程池异常处理
ExecutorService executor = Executors.newFixedThreadPool(10);
executor.execute(() -> {
    try {
        // 业务逻辑
    } catch (Throwable t) {
        // 记录日志,不要吞掉异常
        logger.error("Task failed", t);
    }
});

Python常见原因

python 复制代码
# 1. 循环引用导致GC延迟
import weakref

class Node:
    def __init__(self):
        self.parent = None
        self.children = []
    
    def add_child(self, child):
        self.children.append(child)
        child.parent = weakref.ref(self)  # 使用弱引用避免循环

# 2. 线程池未关闭
executor = ThreadPoolExecutor()
# ...使用后必须关闭
executor.shutdown(wait=True)  # 或上下文管理器 with ThreadPoolExecutor() as e:

# 3. asyncio任务未取消
task = asyncio.create_task(coro())
# 取消未完成的任务
task.cancel()
try:
    await task
except asyncio.CancelledError:
    pass

问题4:上下文切换开销

现象:线程数过多导致CPU时间花在切换上,吞吐量下降。

诊断

bash 复制代码
# Linux查看上下文切换
vmstat 1
pidstat -w -p <pid> 1  # 查看特定进程的cswch/s(自愿切换)和nvcswch/s(非自愿切换)

# Java
jstack <pid> | grep "java.lang.Thread.State" | sort | uniq -c

优化

java 复制代码
// 使用协程/虚拟线程减少切换(Java 21+)
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    IntStream.range(0, 1_000_000).forEach(i -> {
        executor.submit(() -> {
            Thread.sleep(Duration.ofSeconds(1));
            return i;
        });
    });
} // 100万个虚拟线程,实际OS线程只有几十个
python 复制代码
# Python使用asyncio避免线程切换
# 一个线程内调度数万协程,无上下文切换开销

问题5:数据竞争(Data Race)

现象:多个线程同时读写共享数据,结果不可预期。

Java解决方案

java 复制代码
// 方案1:原子类(无锁,CAS)
AtomicInteger counter = new AtomicInteger(0);
counter.incrementAndGet();  // 线程安全

// 方案2:LongAdder(高并发下优于AtomicLong)
LongAdder adder = new LongAdder();
adder.increment();
long sum = adder.sum();

// 方案3:volatile(保证可见性,不保证原子性)
volatile boolean flag = false;  // 状态标志适合

// 方案4:synchronized / Lock
// 方案5:不可变对象(最终方案)
record Point(int x, int y) {}  // Java 16+ record自动不可变

Python解决方案

python 复制代码
import threading

# 方案1:Lock
lock = threading.Lock()
with lock:
    counter += 1

# 方案2:RLock(可重入锁,适合递归)
rlock = threading.RLock()

# 方案3:Semaphore(限流)
sem = threading.Semaphore(10)

# 方案4:原子操作(部分内置操作是原子的)
# 列表的append/pop、字典的getitem/setitem(单个操作)

# 方案5:Queue(线程安全,无需手动加锁)
from queue import Queue
q = Queue()
q.put(item)
item = q.get()

七、监控与诊断工具

Java工具链

bash 复制代码
# 线程Dump分析
jstack -l <pid> > thread_dump.txt

# 可视化工具
# - VisualVM:线程状态实时监控
# - Async-profiler:低开销性能分析
# - JFR (Java Flight Recorder):内置生产级监控

# 代码示例:自定义线程池监控
public class MonitoredThreadPool extends ThreadPoolExecutor {
    private final AtomicLong submittedTasks = new AtomicLong();
    private final AtomicLong completedTasks = new AtomicLong();
    
    @Override
    protected void beforeExecute(Thread t, Runnable r) {
        submittedTasks.incrementAndGet();
        super.beforeExecute(t, r);
    }
    
    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        completedTasks.incrementAndGet();
        if (t != null) {
            // 记录异常
        }
        super.afterExecute(r, t);
    }
    
    public double getCompletionRate() {
        return (double) completedTasks.get() / submittedTasks.get();
    }
}

Python工具链

python 复制代码
# 查看线程信息
import threading
print(threading.enumerate())  # 所有活动线程

# asyncio调试
import asyncio
asyncio.get_event_loop().set_debug(True)  # 启用调试模式

# 性能分析
import cProfile
import pstats

def profile_func():
    with ThreadPoolExecutor() as e:
        list(e.map(some_func, range(100)))

cProfile.run('profile_func()', 'stats')
p = pstats.Stats('stats')
p.sort_stats('cumulative').print_stats(20)

八、总结与选型建议

场景 推荐方案
Java高并发Web服务 Tomcat/Jetty线程池 + CompletableFuture异步化
Java大数据处理 Fork/Join或并行流(parallelStream)
Java微服务编排 WebFlux(Reactor)+ 虚拟线程(Java 21+)
Python爬虫/IO密集型 asyncio + aiohttp(单线程数万并发)
Python数据处理 multiprocessing + shared_memory
Python Web服务 FastAPI/Starlette(基于asyncio)
混合CPU+IO任务 Java:CompletableFuture组合;Python:ProcessPoolExecutor + ThreadPoolExecutor嵌套

多线程编程的核心在于识别瓶颈 (IO bound vs CPU bound)、控制并发度保证数据安全 。现代趋势是向结构化并发 (Java虚拟线程、Python asyncio)和响应式编程演进,以更低的资源成本实现更高的并发能力。

相关推荐
武帝为此1 小时前
【C语言进程与线程】
c语言·开发语言
fox_lht1 小时前
第十一章 错误处理
开发语言·后端·rust
叼烟扛炮1 小时前
C++ 知识点12 构造函数
开发语言·c++·算法·构造函数
Allen_LVyingbo1 小时前
面向医疗群体智能的协同诊疗与群体决策支持系统(上)
数据结构·数据库·人工智能·git·python·动态规划
Byte Wizard1 小时前
C语言指针深入浅出4
c语言·开发语言
java1234_小锋1 小时前
Spring AI 2.0 开发Java Agent智能体 - 结构化输出
java·人工智能·spring
asdfg12589631 小时前
Java 大型项目设计的“内功心法”---面向对象和接口编程
java·开发语言
叼烟扛炮1 小时前
C++第八讲:string 类
开发语言·c++·算法·string
ch.ju1 小时前
Java programming Chapter Three——Array
java·开发语言