Java 多线程基础入门:线程创建与常用方法详解

举报
Brian-Tony 发表于 2026/10/21 10:31:05 2026/10/21
【摘要】 前言多线程是 Java 开发中的核心知识点,也是面试中的高频考点。掌握多线程编程,能让我们写出性能更高、响应更快的程序。本文从最基础的线程创建讲起,带你快速入门 Java 多线程。 一、什么是线程和进程?进程:操作系统中正在运行的程序,是资源分配的基本单位。比如你打开一个浏览器就是一个进程。线程:进程中的一个执行单元,是 CPU 调度的基本单位。一个进程可以包含多个线程,它们共享进程的资源...

前言

多线程是 Java 开发中的核心知识点,也是面试中的高频考点。掌握多线程编程,能让我们写出性能更高、响应更快的程序。本文从最基础的线程创建讲起,带你快速入门 Java 多线程。

一、什么是线程和进程?

  • 进程:操作系统中正在运行的程序,是资源分配的基本单位。比如你打开一个浏览器就是一个进程。
  • 线程:进程中的一个执行单元,是 CPU 调度的基本单位。一个进程可以包含多个线程,它们共享进程的资源。

简单理解:进程是"车间",线程是车间里的"工人"。

二、创建线程的三种方式

1. 继承 Thread 类

public class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("线程执行:" + Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start();
    }
}

2. 实现 Runnable 接口(推荐)

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("线程执行:" + Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable());
        thread.start();
    }
}

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

import java.util.concurrent.*;

public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        return "线程返回结果";
    }

    public static void main(String[] args) throws Exception {
        ExecutorService pool = Executors.newFixedThreadPool(1);
        Future<String> future = pool.submit(new MyCallable());
        System.out.println(future.get());
        pool.shutdown();
    }
}

三种方式对比

方式 优点 缺点
继承 Thread 简单直接 Java 单继承,无法再继承其他类
实现 Runnable 灵活,可继承其他类 无返回值
实现 Callable 有返回值,可抛异常 使用较复杂

实际开发中推荐使用 Runnable 或 Callable,因为 Java 是单继承,实现接口更灵活。

三、线程的常用方法

方法 说明
start() 启动线程,JVM 会调用 run() 方法
run() 线程执行的任务逻辑
sleep(ms) 让当前线程休眠指定毫秒
join() 等待该线程执行完毕
yield() 让出 CPU 时间片
interrupt() 中断线程
isAlive() 判断线程是否存活
getName() 获取线程名称
setDaemon(true) 设置为守护线程

代码示例

public class ThreadMethodDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            for (int i = 1; i <= 5; i++) {
                System.out.println(Thread.currentThread().getName() + ":" + i);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "子线程");

        t.start();
        t.join(); // 等待子线程执行完
        System.out.println("主线程结束");
    }
}

四、线程的生命周期

Java 线程有 6 种状态,定义在 Thread.State 枚举中:

  1. NEW:新建状态,线程对象已创建但还没调用 start()
  2. RUNNABLE:可运行状态,包括就绪和运行中
  3. BLOCKED:阻塞状态,等待获取锁
  4. WAITING:等待状态,无限期等待其他线程通知
  5. TIMED_WAITING:超时等待状态,如调用了 sleep() 或 wait(timeout)
  6. TERMINATED:终止状态,线程执行完毕
NEW → RUNNABLE → BLOCKED/WAITING/TIMED_WAITING → TERMINATED

五、线程安全问题

当多个线程同时操作共享资源时,可能出现数据不一致的问题。

问题示例

public class UnsafeDemo {
    private static int count = 0;

    public static void main(String[] args) throws InterruptedException {
        Runnable task = () -> {
            for (int i = 0; i < 10000; i++) {
                count++;
            }
        };

        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);
        t1.start();
        t2.start();
        t1.join();
        t2.join();

        System.out.println("count = " + count); // 结果通常小于 20000
    }
}

解决方案:synchronized

public class SafeDemo {
    private static int count = 0;
    private static final Object lock = new Object();

    public static void main(String[] args) throws InterruptedException {
        Runnable task = () -> {
            for (int i = 0; i < 10000; i++) {
                synchronized (lock) {
                    count++;
                }
            }
        };

        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);
        t1.start();
        t2.start();
        t1.join();
        t2.join();

        System.out.println("count = " + count); // 结果一定是 20000
    }
}

六、线程池

频繁创建和销毁线程开销很大,线程池可以复用线程,提高性能。

常用线程池

线程池 说明
newFixedThreadPool 固定大小线程池
newCachedThreadPool 可缓存线程池,按需创建
newSingleThreadExecutor 单线程池
newScheduledThreadPool 定时任务线程池

代码示例

import java.util.concurrent.*;

public class ThreadPoolDemo {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(3);

        for (int i = 0; i < 10; i++) {
            final int taskId = i;
            pool.submit(() -> {
                System.out.println("任务" + taskId + "由 " + Thread.currentThread().getName() + " 执行");
            });
        }

        pool.shutdown();
    }
}

注意:实际开发中建议使用 ThreadPoolExecutor 手动创建线程池,避免使用 Executors 工厂方法,因为它们的默认参数可能导致 OOM 等问题。

七、常见面试题

  1. start() 和 run() 的区别?
    start() 会启动新线程并执行 run();直接调用 run() 只是普通方法调用,不会创建新线程。
  2. sleep() 和 wait() 的区别?
    sleep() 是 Thread 的方法,不释放锁;wait() 是 Object 的方法,会释放锁,需要配合 notify()/notifyAll() 使用。
  3. 如何保证线程安全?
    synchronized、ReentrantLock、原子类(AtomicInteger 等)、ThreadLocal、ConcurrentHashMap 等。
  4. volatile 关键字的作用?
    保证可见性和有序性,但不保证原子性。

总结

多线程是 Java 进阶的必经之路。本文介绍了线程创建、常用方法、生命周期、线程安全和线程池等基础知识。建议多动手实践,理解每个 API 的使用场景,为后续学习并发包(JUC)打好基础。


【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。