Java 多线程编程:从基础到实战!

举报
喵手 发表于 2025/03/19 22:28:19 2025/03/19
【摘要】 开篇语哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,...

开篇语

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

  多线程编程是 Java 中的一个核心概念,它允许多个线程同时执行任务,从而提高程序的效率和响应性。在现代应用程序中,多线程编程无处不在,尤其是在处理高并发任务时。今天,我们将从基础到实战深入讲解 Java 的多线程编程,帮助你更好地理解和应用它。

1. 线程基础概念

1.1 什么是线程?

  线程是操作系统能够进行调度的最小单位。每个 Java 程序在启动时,都会自动创建一个主线程。通过多线程编程,多个线程可以同时执行不同的任务。

  线程是属于进程的,每个线程都有自己的执行路径。多线程可以并发地执行任务,提高程序的效率,尤其是在 CPU 密集型和 I/O 密集型任务中。

1.2 线程的生命周期

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

  • 新建(New):线程对象创建后,还未调用 start() 方法时,处于新建状态。
  • 就绪(Runnable):线程调用 start() 方法后,处于就绪状态。操作系统会将就绪的线程分配 CPU 时间片,开始执行任务。
  • 运行(Running):线程获得 CPU 时间片后,进入运行状态,开始执行任务。
  • 阻塞(Blocked):线程在等待某些资源(如 I/O、锁等)时,会进入阻塞状态。
  • 死亡(Dead):线程执行完任务后进入死亡状态。

2. 线程的创建与启动

在 Java 中,创建和启动线程的方式有两种:继承 Thread 类和实现 Runnable 接口。

2.1 继承 Thread

  通过继承 Thread 类并重写 run() 方法来实现线程。然后通过调用 start() 方法来启动线程。

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

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

2.2 实现 Runnable 接口

  通过实现 Runnable 接口,并将 Runnable 实现类传递给 Thread 构造函数,再调用 start() 方法来启动线程。这个方法的优势是支持多继承。

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

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

3. 线程的同步

多线程编程中,一个常见的问题是多个线程访问共享资源时,可能会导致数据不一致的问题。为了解决这个问题,Java 提供了多种同步机制。

3.1 使用 synchronized 关键字

synchronized 是 Java 中用于控制对共享资源的访问的关键字。它可以确保同一时刻只有一个线程能够执行被 synchronized 修饰的代码块。

示例:使用 synchronized 修饰方法

class Counter {
    private int count = 0;

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

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

public class SynchronizedExample {
    public static void main(String[] args) {
        Counter counter = new Counter();

        // 创建多个线程并执行任务
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        });

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("最终计数值:" + counter.getCount());
    }
}

3.2 使用 ReentrantLock

ReentrantLock 是一种更灵活的锁机制,它比 synchronized 更加可控,支持尝试锁、定时锁等高级功能。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

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

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

    public int getCount() {
        return count;
    }
}

public class LockExample {
    public static void main(String[] args) {
        Counter counter = new Counter();

        // 创建多个线程并执行任务
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        });

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("最终计数值:" + counter.getCount());
    }
}

4. 线程的通信

在某些情况下,多个线程需要相互协作,完成任务。Java 提供了 wait()notify()notifyAll() 方法来进行线程间的通信。

4.1 使用 wait()notify()

wait() 方法使当前线程进入等待状态,直到其他线程调用 notify()notifyAll() 方法时,当前线程才会被唤醒。

class SharedResource {
    private boolean flag = false;

    public synchronized void produce() throws InterruptedException {
        while (flag) {
            wait();  // 如果已经生产了,就等待
        }
        System.out.println("生产者生产了一个产品");
        flag = true;
        notify();  // 唤醒消费者
    }

    public synchronized void consume() throws InterruptedException {
        while (!flag) {
            wait();  // 如果没有产品,就等待
        }
        System.out.println("消费者消费了一个产品");
        flag = false;
        notify();  // 唤醒生产者
    }
}

public class WaitNotifyExample {
    public static void main(String[] args) {
        SharedResource resource = new SharedResource();

        // 生产者线程
        Thread producer = new Thread(() -> {
            try {
                while (true) {
                    resource.produce();
                    Thread.sleep(1000);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        // 消费者线程
        Thread consumer = new Thread(() -> {
            try {
                while (true) {
                    resource.consume();
                    Thread.sleep(1000);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        producer.start();
        consumer.start();
    }
}

5. 线程池

  线程池是为了减少线程创建和销毁的开销,提升程序效率而设计的。Java 提供了 ExecutorService 接口和它的实现类 ThreadPoolExecutor 来管理线程池。

5.1 使用 ExecutorService 创建线程池

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

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

        // 提交任务给线程池
        for (int i = 0; i < 5; i++) {
            executor.submit(() -> {
                System.out.println("线程 " + Thread.currentThread().getName() + " 正在执行");
            });
        }

        // 关闭线程池
        executor.shutdown();
    }
}

6. 总结

  多线程编程是 Java 编程中的一个重要部分,它能够提升程序的性能和响应速度。通过学习 Java 中的线程创建、同步、通信和线程池等内容,你可以更好地理解如何在 Java 中实现并发处理。

  今天,我们从 Java 线程的基础概念到高级特性进行了详细的讲解,并通过实例帮助大家更好地理解多线程编程的核心要点。希望这篇文章能够帮助你更好地掌握 Java 多线程编程!

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。


版权声明:本文由作者原创,转载请注明出处,谢谢支持!

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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