Java 多线程系列详解:从基础到高级

107 阅读3分钟

Java 多线程系列详解:从基础到高级

多线程编程是 Java 开发中的重要主题,能够提高程序执行效率和资源利用率。本文是 Java 多线程系列的第一篇,将从多线程的基础知识入手,详细讲解多线程的创建方式、生命周期、常用方法、线程同步机制以及常见问题。


一、什么是多线程?

多线程是一种并发执行任务的方式,允许程序在多个线程之间切换,从而同时运行多个任务,提高程序的执行效率和响应速度。


二、Java 多线程的实现方式

Java 提供了多种创建线程的方法。

1. 继承 Thread 类

通过继承 Thread 类,重写 run() 方法来定义线程执行的内容。

class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("线程执行:" + Thread.currentThread().getName());
    }
}
​
public class Main {
    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        t1.start();  // 启动线程
    }
}

2. 实现 Runnable 接口(推荐)

这种方式更灵活,推荐使用。

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("执行线程:" + Thread.currentThread().getName());
    }
}
​
public class Main {
    public static void main(String[] args) {
        Thread t1 = new Thread(new MyRunnable());
        t1.start();  // 启动线程
    }
}

3. 实现 Callable 接口(带返回值)

Callable 接口支持返回值和异常处理,比 Runnable 更强大。

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
​
class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        return "线程执行:" + Thread.currentThread().getName();
    }
}
​
public class Main {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<String> futureTask = new FutureTask<>(new MyCallable());
        Thread t1 = new Thread(futureTask);
        t1.start();
        System.out.println(futureTask.get());
    }
}

三、线程的生命周期

Java 中线程的生命周期主要包括以下几个阶段:

  1. 新建(New) :线程对象被创建,但未启动。
  2. 就绪(Runnable) :调用 start() 方法,等待 CPU 调度。
  3. 运行(Running) :CPU 调度后开始执行 run() 方法。
  4. 阻塞(Blocked/Waiting) :线程在等待资源时进入该状态。
  5. 终止(Terminated) :线程执行完成或被中断。

四、线程常用方法及示例

方法描述示例代码
start()启动线程t1.start();
run()定义线程运行的逻辑t1.run(); (不推荐)
sleep(long)让线程休眠一段时间Thread.sleep(1000);
yield()暂时放弃 CPU 使用权Thread.yield();
join()等待线程执行完成t1.join();
interrupt()中断线程t1.interrupt();
isAlive()检查线程是否存活t1.isAlive();

示例代码:

class MyThread extends Thread {
    @Override
    public void run() {
        try {
            System.out.println("线程开始:" + Thread.currentThread().getName());
            Thread.sleep(1000);  // 休眠 1 秒
            System.out.println("线程结束:" + Thread.currentThread().getName());
        } catch (InterruptedException e) {
            System.out.println("线程被中断:" + Thread.currentThread().getName());
        }
    }
}
​
public class Main {
    public static void main(String[] args) throws InterruptedException {
        MyThread t1 = new MyThread();
        t1.start();  // 启动线程
        t1.join();   // 等待线程完成
        System.out.println("主线程执行完成");
    }
}

五、线程安全与同步机制

1. 同步代码块(synchronized)

public class SyncExample {
    public void method() {
        synchronized (this) {
            System.out.println("线程:" + Thread.currentThread().getName());
        }
    }
}

2. 同步方法

public class SyncExample {
    public synchronized void syncMethod() {
        System.out.println("同步方法执行:" + Thread.currentThread().getName());
    }
}

3. 静态同步方法

public class SyncExample {
    public static synchronized void staticMethod() {
        System.out.println("静态同步方法:" + Thread.currentThread().getName());
    }
}

六、常见问题与注意事项

1. 为什么使用多线程?

  • 提高程序执行效率
  • 提供更好的用户体验(如响应用户界面)
  • 并发处理多个任务

2. 多线程的主要问题

  • 数据共享问题: 多线程共享变量可能导致数据不一致。
  • 死锁: 多个线程相互等待对方释放资源。
  • 线程阻塞: 等待资源时导致程序挂起。

七、面试常见问题与知识点

  1. Java 中如何创建线程?哪种方式更推荐? 推荐使用 Runnable 接口,灵活性更高。

  2. 线程的生命周期是什么? 新建、就绪、运行、阻塞、终止。

  3. 线程间如何实现通信?

    • 使用 wait()notify()notifyAll()
    • 使用 ConditionLock
  4. 线程安全的集合类有哪些?

    • ConcurrentHashMap
    • CopyOnWriteArrayList
    • BlockingQueue

通过这些基础知识,你应该对 Java 多线程的核心概念有了深入的了解。如果对某个方面感兴趣,欢迎讨论! 😊