创建线程

继承Thread类

public class MyThread extends Thread {
    public void run() {
        // 线程执行代码
    }
}
 
// 使用示例
Thread t = new MyThread();
t.start();

实现Runnable接口

public class MyRunnable implements Runnable {
    public void run() {
        // 线程执行代码
    }
}
 
// 使用示例
Thread t = new Thread(new MyRunnable());
t.start();

实现Callable接口(带返回值)

Warning

前两种存在的问题:假如线程执行完毕后有一些数据需要返回,他们重写的run方法均不能直接返回结果。

import java.util.concurrent.*;
 
public class BasicCallableDemo {
    public static void main(String[] args) throws Exception {
        // 1. 创建Callable任务
        Callable<String> task = () -> {
            Thread.sleep(1000);
            return "任务执行完毕";
        };
 
        // 2. 包装成FutureTask
        FutureTask<String> future = new FutureTask<>(task);
        
        // 3. 直接启动线程(不用线程池)
        new Thread(future).start();
        
        // 4. 获取结果(会阻塞)
        System.out.println(future.get()); // 输出: 任务执行完毕
    }
}
 

线程的常用方法

基础控制方法

  • start(): 启动线程
  • run(): 线程执行体(需重写)
  • sleep(long millis): 线程休眠指定毫秒(静态方法)
  • yield(): 暂停当前线程,让出CPU(静态方法)

状态检查方法

  • isAlive(): 判断线程是否存活
  • isDaemon(): 判断是否为守护线程
  • getState(): 获取线程状态(NEW/RUNNABLE/BLOCKED等)

中断相关

  • interrupt(): 中断线程
  • isInterrupted(): 判断是否被中断
  • interrupted(): 判断并清除中断状态(静态方法)

其他

  • setPriority(int): 设置线程优先级(1-10)
  • setDaemon(boolean): 设置守护线程
  • join(): 等待该线程终止
  • currentThread(): 获取当前线程(静态方法)

线程安全

当多个线程访问共享资源时,可能出现数据不一致问题。解决方案:

  1. 同步代码块

锁对象的使用规范

  • 建议使用共享资源作为锁对象,对于实例方法建议使用this作为锁对象。
  • 对于静态方法建议使用字节码(类名.class)对象作为锁对象。
synchronized(锁对象) {
    // 临界区代码
}
  1. 同步方法
public synchronized void method() {
    // 同步代码
}
  1. Lock接口(更灵活):
final Lock lock = new ReentrantLock(); // 建议final修饰,防止被修改
lock.lock(); // 上锁
try {
    // 临界区代码
} finally {
    lock.unlock(); // 解锁
}

线程同步

等待唤醒机制

// 等待
synchronized(obj) {
    obj.wait();
}
 
// 唤醒
synchronized(obj) {
    obj.notify();  // 随机唤醒一个
    obj.notifyAll(); // 唤醒所有
}

同步工具类

  1. CountDownLatch:等待多个线程完成
  2. CyclicBarrier:线程到达屏障时等待
  3. Semaphore:控制并发线程数

线程池

创建线程池

// 推荐手动创建(避免Executors的潜在问题)
ThreadPoolExecutor executor = new ThreadPoolExecutor(
    5, // 核心线程数
    10, // 最大线程数
    60, // 空闲线程存活时间
    TimeUnit.SECONDS, // 时间单位
    new ArrayBlockingQueue<>(100) // 任务队列
);

处理Runnable任务

executor.execute(() -> {
    System.out.println("执行Runnable任务");
});

处理Callable任务

Future<String> future = executor.submit(() -> {
    Thread.sleep(1000);
    return "Callable结果";
});
System.out.println(future.get()); // 获取返回值

通过Executors创建线程池

// 1. 固定大小线程池
ExecutorService fixedPool = Executors.newFixedThreadPool(5);
 
// 2. 单线程池(保证顺序执行)
ExecutorService singleThread = Executors.newSingleThreadExecutor();
 
// 3. 可缓存线程池(自动扩容)
ExecutorService cachedPool = Executors.newCachedThreadPool();
 
// 4. 定时任务线程池
ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(3);
scheduledPool.schedule(() -> {
    System.out.println("延迟3秒执行");
}, 3, TimeUnit.SECONDS);

注意

Executors创建的线程池可能引发OOM(如CachedThreadPool任务队列无界),生产环境建议手动创建ThreadPoolExecutor

线程池参数配置公式

核心参数配置建议

CPU密集型任务(计算为主):

  • 核心线程数 = CPU核数 + 1
  • 最大线程数 = CPU核数 * 2

IO密集型任务(网络/磁盘IO为主):

  • 核心线程数 = CPU核数 * 2
  • 最大线程数 = CPU核数 / (1 - 阻塞系数)
    • 阻塞系数(经验值0.8~0.9)

获取CPU核数:
int cpuCores = Runtime.getRuntime().availableProcessors();