如何在Java中实现多线程编程

简介: Java多线程编程有三种主要方式:继承Thread类、实现Runnable接口、实现Callable接口(结合Future获取结果),推荐使用Runnable避免单继承限制。通过线程池(如ExecutorService)可高效管理线程,提升性能。多线程共享资源时需注意线程安全,使用synchronized或Lock机制保证数据一致性。适用于并发执行、异步计算等场景。

在Java中实现多线程编程主要有三种核心方式:继承Thread实现Runnable接口实现Callable接口(结合Future。此外,还可以通过线程池(ExecutorService)更高效地管理线程。以下是详细实现方法及代码示例:

一、继承Thread

Thread类是Java线程的基础类,通过继承它并重写run()方法定义线程执行逻辑,调用start()方法启动线程(而非直接调用run())。

// 1. 继承Thread类
class MyThread extends Thread {
   
    // 2. 重写run()方法,定义线程执行逻辑
    @Override
    public void run() {
   
        for (int i = 0; i < 5; i++) {
   
            // Thread.currentThread().getName()获取当前线程名称
            System.out.println(Thread.currentThread().getName() + ":执行第" + i + "次");
            try {
   
                Thread.sleep(500); // 线程休眠500ms(模拟耗时操作)
            } catch (InterruptedException e) {
   
                e.printStackTrace();
            }
        }
    }
}

public class ThreadDemo {
   
    public static void main(String[] args) {
   
        // 3. 创建线程对象
        MyThread thread1 = new MyThread();
        MyThread thread2 = new MyThread();

        // 设置线程名称(可选)
        thread1.setName("线程A");
        thread2.setName("线程B");

        // 4. 启动线程(调用start(),而非run())
        thread1.start();
        thread2.start();
    }
}

输出(顺序可能不同,体现线程并发)

线程A:执行第0次
线程B:执行第0次
线程A:执行第1次
线程B:执行第1次
...

二、实现Runnable接口

Runnable是函数式接口(仅含run()方法),通过实现它定义线程逻辑,再将实例传入Thread类启动。推荐此方式,因为Java单继承,但可多实现。

// 1. 实现Runnable接口
class MyRunnable implements Runnable {
   
    // 2. 实现run()方法
    @Override
    public void run() {
   
        for (int i = 0; i < 5; i++) {
   
            System.out.println(Thread.currentThread().getName() + ":执行第" + i + "次");
            try {
   
                Thread.sleep(500);
            } catch (InterruptedException e) {
   
                e.printStackTrace();
            }
        }
    }
}

public class RunnableDemo {
   
    public static void main(String[] args) {
   
        // 3. 创建Runnable实例
        MyRunnable runnable = new MyRunnable();

        // 4. 将Runnable传入Thread,创建线程对象
        Thread thread1 = new Thread(runnable, "线程C");
        Thread thread2 = new Thread(runnable, "线程D");

        // 5. 启动线程
        thread1.start();
        thread2.start();
    }
}

特点:多个线程可共享同一个Runnable实例的资源(如成员变量),适合多线程协作。

三、实现Callable接口(带返回值)

Callable接口与Runnable类似,但允许线程执行后返回结果,且可抛出受检异常。需结合FutureFutureTask获取结果。

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

// 1. 实现Callable接口,指定返回值类型(此处为Integer)
class MyCallable implements Callable<Integer> {
   
    private int num;

    public MyCallable(int num) {
   
        this.num = num;
    }

    // 2. 实现call()方法(有返回值)
    @Override
    public Integer call() throws Exception {
   
        int sum = 0;
        for (int i = 1; i <= num; i++) {
   
            sum += i;
        }
        System.out.println(Thread.currentThread().getName() + ":计算完成");
        return sum; // 返回结果
    }
}

public class CallableDemo {
   
    public static void main(String[] args) throws ExecutionException, InterruptedException {
   
        // 3. 创建Callable实例
        MyCallable callable = new MyCallable(100);

        // 4. 用FutureTask包装Callable(FutureTask实现了Future和Runnable)
        FutureTask<Integer> futureTask = new FutureTask<>(callable);

        // 5. 传入Thread启动
        Thread thread = new Thread(futureTask, "计算线程");
        thread.start();

        // 6. 调用get()获取结果(会阻塞当前线程,直到子线程执行完毕)
        int result = futureTask.get();
        System.out.println("1~100的和:" + result); // 输出:5050
    }
}

特点:适合需要线程返回结果的场景(如异步计算)。

四、线程池(ExecutorService

频繁创建/销毁线程会消耗资源,线程池可复用线程,提高效率。通过Executors工具类创建线程池(实际开发中推荐ThreadPoolExecutor自定义)。

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

public class ThreadPoolDemo {
   
    public static void main(String[] args) {
   
        // 1. 创建固定大小的线程池(3个线程)
        ExecutorService executor = Executors.newFixedThreadPool(3);

        // 2. 提交任务(Runnable或Callable)
        for (int i = 0; i < 5; i++) {
   
            final int taskNum = i;
            executor.submit(new Runnable() {
   
                @Override
                public void run() {
   
                    System.out.println(Thread.currentThread().getName() + ":执行任务" + taskNum);
                    try {
   
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
   
                        e.printStackTrace();
                    }
                }
            });
        }

        // 3. 关闭线程池(不再接受新任务,等待现有任务完成)
        executor.shutdown();
    }
}

常用线程池类型

  • newFixedThreadPool(n):固定大小的线程池
  • newCachedThreadPool():可缓存的线程池(线程数动态调整)
  • newSingleThreadExecutor():单线程池(任务串行执行)
  • newScheduledThreadPool(n):支持定时/周期性任务的线程池

五、线程常用方法

方法 说明
start() 启动线程(底层调用run()
run() 线程执行逻辑(需重写)
sleep(long ms) 让当前线程休眠指定毫秒(不会释放锁)
join() 等待该线程执行完毕后,再继续执行其他线程
yield() 让出CPU资源,让其他线程优先执行
setPriority(int) 设置线程优先级(1~10,默认5)
isAlive() 判断线程是否存活

六、线程安全问题

多线程共享资源时可能出现数据不一致,需通过同步机制解决:

  • synchronized关键字(同步方法/代码块)
  • Lock接口(如ReentrantLock

示例(synchronized解决线程安全)

class Counter {
   
    private int count = 0;

    // 同步方法:保证同一时间只有一个线程执行
    public synchronized void increment() {
   
        count++;
    }

    public int getCount() {
   
        return count;
    }
}

public class ThreadSafety {
   
    public static void main(String[] args) throws InterruptedException {
   
        Counter counter = new Counter();
        Thread t1 = new Thread(() -> {
   
            for (int i = 0; i < 10000; i++) {
   
                counter.increment();
            }
        });
        Thread t2 = new Thread(() -> {
   
            for (int i = 0; i < 10000; i++) {
   
                counter.increment();
            }
        });

        t1.start();
        t2.start();
        t1.join(); // 等待t1完成
        t2.join(); // 等待t2完成

        System.out.println("最终计数:" + counter.getCount()); // 正确输出20000(无同步可能小于20000)
    }
}

总结

  • 简单场景:用ThreadRunnable(推荐Runnable)。
  • 需要返回值:用Callable + Future
  • 高效管理线程:用线程池。
  • 多线程共享资源:需考虑线程安全(synchronizedLock)。

多线程编程的核心是并发协作资源同步,实际开发中需根据场景选择合适的实现方式。

相关文章
|
2月前
|
人工智能 自然语言处理 安全
SOFA AI 网关基于 Higress 的落地实践
SOFA 商业化团队为满足客户 AI 业务的发展需求,基于开源 Higress 内核构建,推出了 SOFA AI 网关,专为 SOFA 场景深度优化、能力增强,是面向 AI 需求的智能网关解决方案。
246 22
|
2月前
|
IDE Java 编译器
java编程最基础学习
Java入门需掌握:环境搭建、基础语法、面向对象、数组集合与异常处理。通过实践编写简单程序,逐步深入学习,打牢编程基础。
226 1
|
2月前
|
监控 算法 固态存储
Ashampoo UnInstaller使用教程!高效彻底的软件卸载助手(附下载)
Ashampoo UnInstaller 可彻底卸载软件并清理残留文件、注册表等,提升系统速度与稳定性。支持批量卸载、程序迁移、安装保护及实时监控,操作简单,是优化电脑性能的高效工具。
254 1
|
22天前
|
文字识别 安全 程序员
PowerToys微软官方效率工具实操教程!Windows系统增强神器!
PowerToys是微软官方推出的免费开源工具集,集成20余款高效插件,如窗口管理、快速启动、批量重命名、OCR文字提取等,显著提升Windows使用体验,支持多屏协作、快捷操作,安全稳定,持续更新,适合各类用户优化工作效率。
185 6
|
算法 Linux 数据处理
《操作系统》—— 处理机调度算法
《操作系统》—— 处理机调度算法
3682 1
|
存储 缓存 关系型数据库
海量数据去重的hash,bitmap与布隆过滤器Bloom Filter
海量数据去重的hash,bitmap与布隆过滤器Bloom Filter
326 1
|
4天前
|
存储 传感器 监控
RFID实现仓储物流透明化与智能化管理
RFID 技术在仓储物流领域,是当前提升效率和准确性的核心方案之一。其核心价值在于通过非接触式自动识别,RFID实现仓储物流透明化与智能化管理。
|
24天前
|
人工智能 前端开发 数据挖掘
AI学习全景图:从大模型到RAG,从工具到变现,一条从0到1的路线
告别碎片化学习!本文系统梳理AI知识五层结构:从基础认知到商业变现,提供完整学习路径与优质资源链接。帮你构建AI知识网络,实现从工具使用到能力落地的跃迁。
561 2
|
3天前
|
传感器 人工智能 算法
2025 全球 GEO 行业观察:双轮驱动(市场 + 技术),AI 时代品牌新基建的破局之道
AI重构信息分发,GEO成品牌新基建。2025年AI搜索占全球63%,传统SEO失效,生成式引擎优化(GEO)通过结构化数据、语义适配与权威构建,助力内容在AI答案中优先被引。本文解析GEO六大核心挑战与落地策略。
|
5天前
|
存储 运维 安全
化工厂人员定位从技术支撑、应用价值到部署与选型要点详解(二)
本文深入解析化工厂人员定位技术,聚焦UWB高精度定位、工业级防护设计与数据安全,阐述其在安全管控、流程规范、合规追溯等方面的应用价值,并提供部署选型与运维培训的实用建议,助力企业构建全流程闭环安全管理体系。如果您想进一步了解定位的案例,欢迎关注、评论留言~也可搜索lbs智能定位。

热门文章

最新文章