首页 > 编程语言 >深入 Java 多线程:解锁并发编程的奥秘

深入 Java 多线程:解锁并发编程的奥秘

时间:2024-11-12 16:18:56浏览次数:3  
标签:Java Thread 解锁 System 线程 println new 多线程 out

在当今的软件开发世界中,性能和高并发是衡量一个应用程序成败的关键因素。无论是处理高流量的网络请求、执行复杂的数据分析任务,还是管理后台服务中的资源,Java 多线程编程都是开发者必备的技能之一。本文将带领你深入 Java 多线程的世界,解锁并发编程的奥秘。


1. 并发与并行的区别:你知道吗?

在开始讨论多线程之前,我们先来澄清一个常见的误解:并发(Concurrency)和并行(Parallelism)并不是一回事。

  • 并发:多个任务在同一时间段内交替执行,给人一种同时执行的感觉,但实际上是在时间片内快速切换。常见的场景是单核处理器的任务调度。
  • 并行:多个任务在同一时刻真正地同时执行,通常依赖于多核处理器或多台机器。

理解这两个概念是学习多线程编程的第一步。


2. Java 多线程基础:Thread 与 Runnable

Java 提供了两种创建线程的方式:继承 Thread 类和实现 Runnable 接口。

  • 继承 Thread 类

    class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println("Hello from MyThread!");
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            MyThread thread = new MyThread();
            thread.start();
        }
    }
    
  • 实现 Runnable 接口

    class MyRunnable implements Runnable {
        @Override
        public void run() {
            System.out.println("Hello from MyRunnable!");
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            Thread thread = new Thread(new MyRunnable());
            thread.start();
        }
    }
    

推荐:尽管两者都能实现多线程,但更推荐使用 Runnable,因为它更灵活,符合面向对象的设计原则(单一职责原则)。


3. 线程的生命周期:掌握线程的状态转换

了解线程的生命周期是多线程编程的关键。Java 中的线程有以下几种状态:

  • 新建(New):线程对象被创建,但还未调用 start() 方法。
  • 运行(Runnable):线程正在执行或准备执行。
  • 阻塞(Blocked):线程因等待 I/O 操作、锁或其他资源而暂停执行。
  • 等待(Waiting):线程因调用 wait() 或 join() 方法而进入等待状态。
  • 超时等待(Timed Waiting):线程因调用 sleep(long) 或 wait(long) 方法而进入超时等待状态。
  • 终止(Terminated):线程执行完毕,进入终止状态。
public class ThreadStatesDemo {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        System.out.println("State: " + thread.getState()); // NEW

        thread.start();
        System.out.println("State: " + thread.getState()); // RUNNABLE

        try {
            Thread.sleep(500);
            System.out.println("State: " + thread.getState()); // TIMED_WAITING

            thread.join();
            System.out.println("State: " + thread.getState()); // TERMINATED
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}


4. 线程同步:守护线程与锁机制

多线程编程中,线程同步是一个重要的话题。Java 提供了多种同步机制来确保线程安全,包括 synchronized 关键字和 Lock 接口。

  • synchronized 关键字

    public synchronized void doSomething() {
        // 同步代码块
    }
    
  • Lock 接口

    Lock lock = new ReentrantLock();
    
    public void doSomething() {
        lock.lock();
        try {
            // 同步代码块
        } finally {
            lock.unlock();
        }
    }
    

注意:使用 Lock 接口时,务必在 finally 块中释放锁,以避免死锁问题。


5. 线程池:高效管理线程资源

在实际开发中,手动创建和管理线程可能会导致资源浪费和性能问题。Java 提供了 ExecutorService 接口和 ThreadPoolExecutor 类来高效管理线程池。

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

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

        for (int i = 0; i < 10; i++) {
            executorService.submit(() -> {
                System.out.println("Task running in " + Thread.currentThread().getName());
            });
        }

        executorService.shutdown();
    }
}

优势:线程池可以复用线程,减少线程创建和销毁的开销,提高系统性能。


6. 并发工具类:CountDownLatch、CyclicBarrier 与 Semaphore

Java 还提供了许多并发工具类来简化多线程编程:

  • CountDownLatch:允许一个或多个线程等待其他线程完成操作。

    CountDownLatch latch = new CountDownLatch(3);
    
    new Thread(() -> {
        System.out.println("Task 1 done");
        latch.countDown();
    }).start();
    
    new Thread(() -> {
        System.out.println("Task 2 done");
        latch.countDown();
    }).start();
    
    new Thread(() -> {
        System.out.println("Task 3 done");
        latch.countDown();
    }).start();
    
    latch.await(); // 等待所有任务完成
    System.out.println("All tasks done");
    
  • CyclicBarrier:允许多个线程相互等待,直到所有线程都到达某个屏障点。

    CyclicBarrier barrier = new CyclicBarrier(3, () -> {
        System.out.println("All tasks reached barrier");
    });
    
    new Thread(() -> {
        System.out.println("Task 1 reached barrier");
        barrier.await();
    }).start();
    
    new Thread(() -> {
        System.out.println("Task 2 reached barrier");
        barrier.await();
    }).start();
    
    new Thread(() -> {
        System.out.println("Task 3 reached barrier");
        barrier.await();
    }).start();
    
  • Semaphore:用于控制同时访问某个资源的线程数量。

    Semaphore semaphore = new Semaphore(2);
    
    new Thread(() -> {
        try {
            semaphore.acquire();
            System.out.println("Task 1 acquired resource");
            Thread.sleep(1000);
            semaphore.release();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }).start();
    
    new Thread(() -> {
        try {
            semaphore.acquire();
            System.out.println("Task 2 acquired resource");
            Thread.sleep(1000);
            semaphore.release();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }).start();
    

7. 总结与展望

Java 多线程编程是一门深奥且有趣的学问,掌握它不仅能提升程序的性能,还能让你在面对高并发场景时游刃有余。从基础的 Thread 和 Runnable 到复杂的并发工具类,每一步都是对并发编程理解的深化。

未来,随着 Java 版本的不断更新,多线程编程将会更加高效和易用。期待你在这条并发编程的道路上继续探索,解锁更多的奥秘!


拓展阅读


希望这篇文章能激发你对 Java 多线程编程的兴趣,并在实际开发中助你一臂之力!

标签:Java,Thread,解锁,System,线程,println,new,多线程,out
From: https://blog.csdn.net/Zyj_0101/article/details/143717728

相关文章

  • 解锁视觉-文本双编码:CLIP类似模型的多GPU训练
    UnlockingVision-TextDual-Encoding:Multi-GPUTrainingofaCLIP-LikeModelROCmBlogs2024年4月24日,由SeanSong撰写。在本博客中,我们将构建一个类似CLIP的视觉-文本双编码器模型,并在AMDGPU上使用ROCm对其进行微调,使用COCO数据集。这项工作受到CLIP原理和HuggingF......
  • 2024年Java 八股文-基础篇
    1.为什么说Java语言“编译与解释并存”?高级编程语言按照程序的执行方式分为编译型和解释型两种。简单来说,编译型语言是指编译器针对特定的操作系统将源代码一次性翻译成可被该平台执行的机器码;解释型语言是指解释器对源程序逐行解释成特定平台的机器码并立即执行。比如,你......
  • Java中2个Integer比较相同的4种方式
    Java中2个Integer比较相同的4种方式概要使用前切记Integer的范围是【-128~127】例如:Integera=128;Integerb=128;1,使用==比较【-128~127】区间内返回true,否则返回false//==比较if(a==b){System.out.println("a,b使用==比较返回结果:true");......
  • 20天精通Java,day1
    面向对象编程static(静态):修饰成员变量和成员方法。类变量和类方法:有static修饰,属于类,在计算机中只有一份,会被类的全部对象共享。既可以通过类名访问(推荐),也可以通过对象名访问。类变量应用场景:在开发中如果某个数据只需要一份,且希望能够被共享(访问,修改),则该数据可以被定义成类......
  • 【JAVA】Java基础—面向对象编程:构造方法-实现一个Car类,包含多个构造方法,创建不同的汽
    在Java中,构造方法则是用于创建对象的特殊方法。通过构造方法,可以在创建对象时初始化其属性。构造方法的重载允许我们根据不同的需求定义多个构造方法,从而灵活地创建对象。我们可以将汽车的构造方法比作汽车的配置选项。比如,当你购买一辆汽车时,你可以选择不同的配置,如颜色、型......
  • 新手入门Java自动化测试的利器:Selenium WebDriver
    新手入门Java自动化测试的利器:SeleniumWebDriver今天我们将深入探讨一款强大的Java自动化测试工具——SeleniumWebDriver。在正式介绍SeleniumWebDriver之前,让我们首先对Selenium本身进行简要概述,以便更好地理解其背景和功能。官方学习网站:https://www.selenium.dev/Sele......
  • ssm093基于Java Web的毕业生就业状况管理系统设计与实现+jsp(论文+源码)_kaic
     毕业设计(论文)题目:毕业生就业状况管理系统设计与实现摘 要现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本毕业生就业状况管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内......
  • javaWeb开发实战:spring MVC+MyBatis实现网页登录验证
    1.环境和工具Idea2019、Tomcat8、Jdk82.新建springMVC项目打开idea,新建项目,选择springMVC->next:填写项目名、路径->finish完成创建3.项目属性配置文件(file)->项目结构:检查sdk、模块设置是否正确。4.运行调试配置Addconfigration点击“+”号,选择tomcat->loca......
  • 基于Java+SpringBoot+Vue+HTML5人职匹配推荐系统(源码+LW+调试文档+讲解等)/人职匹配/
    博主介绍......
  • 基于Java+SpringBoot+Vue+HTML5的网上商城系统(源码+LW+调试文档+讲解等)/网上商城系
    博主介绍......