温馨提示×

Ubuntu Java多线程编程指南

小樊
44
2025-09-23 00:53:37
栏目: 编程语言

Ubuntu Java多线程编程指南

1. 环境准备

在Ubuntu上进行Java多线程编程前,需确保已安装OpenJDK 17+(推荐):

sudo apt update
sudo apt install openjdk-17-jdk

验证安装:

java -version  # 查看JDK版本
javac -version # 查看编译器版本

2. 线程创建:两种基础方式

Java中创建线程的核心方式有两种,推荐优先使用Runnable接口(避免单继承局限性):

  • 继承Thread类
    class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " is running.");
        }
    }
    public class Main {
        public static void main(String[] args) {
            MyThread thread = new MyThread();
            thread.start(); // 启动线程(自动调用run())
        }
    }
    
  • 实现Runnable接口
    class MyRunnable implements Runnable {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " is running.");
        }
    }
    public class Main {
        public static void main(String[] args) {
            Thread thread = new Thread(new MyRunnable());
            thread.start();
        }
    }
    

3. 线程同步:解决数据竞争

多线程访问共享资源时,需通过同步机制保证数据一致性:

  • synchronized关键字:最基础的同步方式,可修饰实例方法(锁当前对象)、静态方法(锁Class对象)或代码块(锁指定对象)。
    class Counter {
        private int count = 0;
        // 同步实例方法(锁当前对象)
        public synchronized void increment() {
            count++;
        }
        // 同步代码块(锁this对象)
        public void safeIncrement() {
            synchronized (this) {
                count++;
            }
        }
    }
    
  • ReentrantLock显式锁:提供更灵活的锁控制(如尝试获取锁、超时、公平锁)。
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    class Counter {
        private int count = 0;
        private final Lock lock = new ReentrantLock();
        public void increment() {
            lock.lock(); // 获取锁
            try {
                count++; // 临界区代码
            } finally {
                lock.unlock(); // 释放锁(必须)
            }
        }
    }
    

4. 线程池:高效管理线程

线程池通过复用线程减少创建/销毁开销,提升性能。Java提供了ExecutorService接口及Executors工具类:

  • 创建固定大小线程池
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    public class Main {
        public static void main(String[] args) {
            ExecutorService executor = Executors.newFixedThreadPool(5); // 5个线程
            for (int i = 0; i < 10; i++) {
                executor.submit(() -> {
                    System.out.println(Thread.currentThread().getName() + " is processing task.");
                });
            }
            executor.shutdown(); // 关闭线程池(不再接受新任务)
        }
    }
    
  • 使用缓存线程池(适合短生命周期任务):
    ExecutorService cachedPool = Executors.newCachedThreadPool();
    

5. 并发工具类:简化复杂场景

Java的java.util.concurrent包提供了多种高级工具类,解决常见并发问题:

  • CountDownLatch:等待多个线程完成任务后再继续主线程。
    import java.util.concurrent.CountDownLatch;
    public class Main {
        public static void main(String[] args) throws InterruptedException {
            CountDownLatch latch = new CountDownLatch(3); // 需等待3个线程
            for (int i = 0; i < 3; i++) {
                new Thread(() -> {
                    System.out.println(Thread.currentThread().getName() + " is working.");
                    latch.countDown(); // 任务完成,计数减1
                }).start();
            }
            latch.await(); // 主线程等待计数归零
            System.out.println("All tasks are done.");
        }
    }
    
  • Semaphore:控制同时访问资源的线程数量(如限流)。
    import java.util.concurrent.Semaphore;
    class ResourcePool {
        private final Semaphore semaphore = new Semaphore(3); // 允许3个线程同时访问
        public void useResource() {
            try {
                semaphore.acquire(); // 获取许可
                System.out.println(Thread.currentThread().getName() + " is using resource.");
                Thread.sleep(1000); // 模拟资源使用
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                semaphore.release(); // 释放许可
            }
        }
    }
    

6. 并发集合:线程安全的容器

Java提供了线程安全的集合类,避免手动同步的复杂性:

  • ConcurrentHashMap:高并发场景下的Map实现(性能优于synchronized HashMap)。
    import java.util.concurrent.ConcurrentHashMap;
    public class Main {
        public static void main(String[] args) {
            ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
            map.put("key1", 1);
            map.put("key2", 2);
            System.out.println(map.get("key1")); // 输出1
        }
    }
    
  • CopyOnWriteArrayList:适合读多写少的场景(写操作复制新数组,不影响读线程)。
    import java.util.concurrent.CopyOnWriteArrayList;
    public class Main {
        public static void main(String[] args) {
            CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
            list.add("item1");
            list.add("item2");
            for (String item : list) {
                System.out.println(item); // 安全遍历
            }
        }
    }
    

7. 原子操作:无锁编程

对于简单的数值操作,可使用java.util.concurrent.atomic包中的原子类(如AtomicInteger),无需加锁即可保证原子性:

import java.util.concurrent.atomic.AtomicInteger;
class Counter {
    private AtomicInteger count = new AtomicInteger(0);
    public void increment() {
        count.incrementAndGet(); // 原子递增
    }
    public int getCount() {
        return count.get();
    }
}

8. 调试与优化技巧

  • 使用IDE调试:IntelliJ IDEA/Eclipse可查看线程状态(如运行、阻塞)、调用栈,帮助定位死锁、竞争问题。
  • 监控工具:通过jvisualvm(JDK自带)监控线程池状态、CPU使用率、内存占用,调整线程池大小(建议设置为CPU核心数的1~2倍)。
  • 避免死锁:确保锁的获取顺序一致(如所有线程先锁A再锁B),减少锁的持有时间。

通过以上步骤,可在Ubuntu上高效实现Java多线程编程,兼顾性能与安全性。

0