首页主机资讯Java在Ubuntu上的多线程编程教程

Java在Ubuntu上的多线程编程教程

时间2026-01-16 18:24:04发布访客分类主机资讯浏览1394
导读:在 Ubuntu 上进行 Java 多线程编程的入门与实战教程 一 环境准备 安装 OpenJDK(Ubuntu 推荐使用 OpenJDK 17 或 21 LTS): 更新索引并安装:sudo apt update &&...

在 Ubuntu 上进行 Java 多线程编程的入门与实战教程

一 环境准备

  • 安装 OpenJDK(Ubuntu 推荐使用 OpenJDK 17 或 21 LTS):
    • 更新索引并安装:sudo apt update & & sudo apt install openjdk-17-jdk
    • 验证安装:java -version、javac -version
  • 可选 配置 JAVA_HOME(便于部分工具识别 JDK 路径):
    • 查找路径:update-alternatives --config java
    • 写入配置(示例为 bash):echo ‘export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64’ > > ~/.bashrc & & source ~/.bashrc
  • 说明:在 Ubuntu 上开发与运行 Java 多线程程序与在其他 Linux 发行版一致,关键在于正确安装 JDK 并使用 javac/java 命令。

二 三种创建线程的方式

  • 方式一 继承 Thread
    • 要点:重写 run(),调用 start() 启动新线程
    • 适用:简单示例或快速验证
  • 方式二 实现 Runnable
    • 要点:任务与线程对象解耦,便于复用与组合
    • 适用:生产代码更推荐
  • 方式三 使用 Executor 框架(推荐)
    • 要点:通过 ExecutorService 管理线程生命周期与资源,支持 Runnable/Callable、Future 等
    • 适用:并发任务编排、线程池复用、获取返回值与异常处理
  • 线程生命周期速记:新建 New → 就绪 Runnable → 运行 Running → 阻塞 Blocked → 终止 Terminated。

三 完整示例 线程池 Callable Future 与同步

  • 功能:使用固定线程池并行计算 1…N 的求和,演示 Callable/Future、线程安全计数与优雅关闭
  • 代码示例:
import java.util.concurrent.*;


public class ThreadPoolSum {

    // 线程安全计数器
    static class Counter {
    
        private final Object lock = new Object();
    
        private int n = 0;

        void add(int delta) {
 synchronized (lock) {
     n += delta;
 }
 }

        int get() {
 synchronized (lock) {
     return n;
 }
 }

    }
    

    static class SumTask implements Callable<
    Long>
 {
    
        private final long from, to;

        SumTask(long from, long to) {
     this.from = from;
     this.to = to;
 }

        @Override public Long call() {
    
            long sum = 0;
    
            for (long i = from;
     i <
    = to;
     i++) sum += i;

            // 模拟少量 I/O 或计算抖动
            try {
     Thread.sleep(1);
 }
 catch (InterruptedException ignored) {
}
    
            return sum;

        }

    }


    public static void main(String[] args) throws Exception {
    
        int n = 1_000_000;
    
        int threads = Runtime.getRuntime().availableProcessors();
     // 贴近 CPU 核心数
        ExecutorService exec = Executors.newFixedThreadPool(threads);
    

        long t0 = System.nanoTime();
    
        Future<
    Long>
    [] futures = new Future[threads];
    
        long chunk = n / threads;
    
        for (int i = 0;
     i <
     threads;
 i++) {
    
            long from = i * chunk + 1;
    
            long to = (i == threads - 1) ? n : (i + 1) * chunk;
    
            futures[i] = exec.submit(new SumTask(from, to));

        }
    

        long total = 0;
    
        for (Future<
    Long>
     f : futures) total += f.get();
     // 阻塞等待结果
        long t1 = System.nanoTime();
    

        exec.shutdown();
    
        exec.awaitTermination(10, TimeUnit.SECONDS);
    

        System.out.printf("Sum[1..%d] = %d, 耗时 %.3f ms%n", n, total, (t1 - t0) / 1_000_000.0);

    }

}
    
  • 编译与运行:
    • javac ThreadPoolSum.java
    • java ThreadPoolSum
  • 要点:
    • 使用 ExecutorService 管理线程,避免频繁创建/销毁线程
    • Callable/Future 可获取任务返回值与异常
    • 共享数据使用 synchronizedjava.util.concurrent 工具类保证线程安全。

四 线程安全与常见并发工具

  • 同步机制
    • synchronized 方法/代码块:保证同一时刻只有一个线程进入临界区
    • ReentrantLock:显式锁,支持尝试锁、超时、公平锁等更灵活的语义
  • 并发容器
    • ConcurrentHashMap、CopyOnWriteArrayList 等,在高并发读写场景更安全高效
  • 同步辅助类
    • CountDownLatch、CyclicBarrier、Semaphore 等,用于线程协作与限流
  • 实践建议
    • 优先使用 Executor 框架 与并发容器,减少手动 new Thread
    • 明确共享可变状态的访问边界,尽量缩小同步范围
    • 正确处理 InterruptedException,避免吞掉中断信号
    • 任务拆分粒度与线程数匹配:CPU 密集型可接近 CPU 核心数,I/O 密集型可适当增加线程数以提升吞吐。

五 调试与排错建议

  • 使用 IDE 的断点与线程视图观察线程状态、锁竞争与调用栈
  • 添加日志(含线程名与时间戳)以还原并发时序
  • 利用 jstack 抓取 Java 线程转储,分析死锁、阻塞与热点
  • 对共享可变状态进行最小化共享,优先使用不可变对象或线程安全容器
  • 单元测试 + 压力测试结合,覆盖边界与异常路径,验证线程安全与性能回归

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!


若转载请注明出处: Java在Ubuntu上的多线程编程教程
本文地址: https://pptw.com/jishu/781734.html
如何在Debian上整合Golang日志 如何在Debian上备份Golang日志

游客 回复需填写必要信息