📌 目录

  1. Java 多线程编程简介
  2. Java 创建线程的方式
    • 2.1 继承 Thread
    • 2.2 实现 Runnable 接口
    • 2.3 使用 ExecutorService
  3. 线程生命周期
  4. 线程同步
    • 4.1 使用 synchronized 关键字
    • 4.2 使用 ReentrantLock
  5. 线程间通信
  6. 线程池
  7. 常见的多线程类
  8. 总结
  9. 参考资料
  10. 出站链接

1. Java 多线程编程简介

多线程是指在同一个程序中,可以同时运行多个线程。每个线程都有自己的执行路径,但它们共享程序的资源。多线程的使用可以提高程序的效率,特别是在需要处理大量计算或等待外部资源的情况下。Java 提供了多种方式来实现多线程编程,包括继承 Thread 类、实现 Runnable 接口以及使用线程池等。


2. Java 创建线程的方式

2.1 继承 Thread

一种创建线程的方法是通过继承 Thread 类并重写其 run() 方法。

class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("Thread is running");
    }

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

在这个例子中,MyThread 类继承了 Thread 类,并重写了 run() 方法。通过调用 start() 方法来启动线程。

2.2 实现 Runnable 接口

另一种创建线程的方法是实现 Runnable 接口并将其传递给 Thread 类的构造函数。

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("Runnable thread is running");
    }

    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();  // 启动线程
    }
}

通过实现 Runnable 接口,我们可以将任务与线程分开,允许多个线程共享同一个任务。Runnable 更适用于任务的重用。

2.3 使用 ExecutorService

ExecutorService 提供了一种更为高级和灵活的方式来管理线程池,推荐用于大多数场景。通过 ExecutorService,我们可以有效地管理线程池中的线程,并提供任务的执行和管理。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("Executor service thread is running");
    }

    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(10);  // 创建一个线程池
        executor.submit(new MyRunnable());  // 提交任务
        executor.shutdown();  // 关闭线程池
    }
}

ExecutorService 通过 submit() 提交任务,并且支持更灵活的线程管理,如线程池大小的设置、任务的提交等。


3. 线程生命周期

线程的生命周期可以分为以下几个状态:

  1. 新建状态 (New):线程被创建但尚未启动。
  2. 可运行状态 (Runnable):线程已经启动,正在等待 CPU 时间片的分配。
  3. 阻塞状态 (Blocked):线程等待资源(如 I/O 操作、锁)释放。
  4. 等待状态 (Waiting):线程等待其他线程的某些条件发生。
  5. 超时等待状态 (Timed Waiting):线程等待一段时间。
  6. 终止状态 (Terminated):线程执行完毕或因异常终止。

4. 线程同步

在多线程环境中,多个线程可能会共享同一资源,因此需要保证对共享资源的访问是互斥的。Java 提供了几种方式来实现线程同步。

4.1 使用 synchronized 关键字

synchronized 关键字可以用来修饰方法或代码块,确保同一时刻只有一个线程能够访问共享资源。

class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public synchronized int getCount() {
        return count;
    }
}

通过在方法上添加 synchronized 关键字,我们确保了多个线程对 increment()getCount() 方法的访问是互斥的。

4.2 使用 ReentrantLock

ReentrantLock 提供了比 synchronized 更灵活的锁机制,支持超时、可中断等高级特性。

import java.util.concurrent.locks.ReentrantLock;

class Counter {
    private int count = 0;
    private final ReentrantLock lock = new ReentrantLock();

    public void increment() {
        lock.lock();  // 获取锁
        try {
            count++;
        } finally {
            lock.unlock();  // 释放锁
        }
    }

    public int getCount() {
        return count;
    }
}

ReentrantLock 允许更精细的控制,例如尝试加锁或设置加锁的超时时间。


5. 线程间通信

线程间通信是指线程之间相互协调,以实现任务的同步和数据的共享。常见的线程间通信方法包括 wait()notify()notifyAll()

class SharedResource {
    private int count = 0;

    public synchronized void increment() {
        count++;
        notify();  // 通知等待的线程
    }

    public synchronized void waitForCondition() throws InterruptedException {
        while (count == 0) {
            wait();  // 等待其他线程的通知
        }
    }
}

在这个例子中,waitForCondition() 方法会在 count 为 0 时让线程进入等待状态,直到其他线程调用 notify() 方法唤醒它。


6. 线程池

线程池是一种资源管理机制,它通过重复使用线程来减少频繁创建和销毁线程的开销。Java 提供了 ExecutorService 接口以及几个实现类来管理线程池。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExample {
    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 running");
            });
        }
        executor.shutdown();  // 关闭线程池
    }
}

线程池通过 Executors 类提供了多种方式创建不同类型的线程池,如固定大小的线程池 (newFixedThreadPool)、单个线程池 (newSingleThreadExecutor) 和可缓存的线程池 (newCachedThreadPool)。


7. 常见的多线程类

  • Thread: Java 提供的基本线程类。
  • Runnable: 定义线程任务的接口,通常与 Thread 配合使用。
  • ExecutorService: 提供更高级的线程池管理。
  • ReentrantLock: 提供更灵活的锁控制机制。
  • CountDownLatch: 用于控制多个线程等待某个事件的发生。
  • CyclicBarrier: 使一组线程互相等待直到达到某个公共屏障点。
  • Semaphore: 控制对某些资源的访问数目。

8. 总结

Java 多线程编程是一个非常强大的工具,能够使程序在需要时执行并行处理。通过合理使用线程池、同步机制、线程间通信等技术,可以有效提高程序的性能和可靠性。然而,线程编程也带来了许多挑战,如死锁、资源竞争等问题,需要谨慎设计和管理。


9. 参考资料


10. 出站链接