《Java编程中第17章的并发基础探索》

《Java编程中第17章的并发基础探究》

《Java编程中第17章的并发基础探索》

引言

在当下的软件开发领域,并发编程已然成为一项不可或缺的技能。随着多核处理器的广泛应用,充分利用系统资源、提升程序运行效率变得愈发关键。Java为开发者提供了强大的并发编程支持,使得编写高效的多线程程序成为可能。本章将会详尽阐释Java并发编程的基础内容,涵盖线程的创建、状态把控、同步机制以及常用的并发工具类等方面。

《Java编程中第17章的并发基础探索》

17.1 Java多线程概览

多线程指的是在一个程序里同时运行多个独立的执行流程(线程),每个线程能够执行不同的任务。与单线程相比,多线程具备如下优势:

  • 提升程序的响应速度
  • 充分利用多核处理器的资源
  • 便于开展异步操作

在Java中,线程是程序执行的最小单元,一个进程能够包含多个线程,这些线程共享进程的资源,但各自拥有独立的执行栈和程序计数器。

《Java编程中第17章的并发基础探索》

多线程的应用场景

  • 图形界面应用程序(将UI线程与后台处理线程分离)
  • 服务器程序(同时处理多个客户端请求)
  • 数据处理(并行处理大量数据)
  • 异步任务(例如文件下载、数据加载等)

17.2 创建任务与线程

在Java中,创建线程主要有两种途径:实现Runnable接口和继承Thread类。

17.2.1 实现Runnable接口

Runnable接口仅有一个run()方法,用于定义线程要执行的任务。实现Runnable接口后,需将其实例传递给Thread类的构造方法,而后调用start()方法启动线程。

/**
 * 借助Runnable接口创建线程的示例
 */
public class RunnableExample implements Runnable {
    private String threadName;

    public RunnableExample(String name) {
        threadName = name;
        System.out.println("创建线程: " + threadName);
    }

    // 线程执行的任务
    public void run() {
        System.out.println("启动线程: " + threadName);
        try {
            for (int i = 4; i > 0; i--) {
                System.out.println("线程 " + threadName + ": " + i);
                // 让线程暂停一段时间
                Thread.sleep(50);
            }
        } catch (InterruptedException e) {
            System.out.println("线程 " + threadName + " 被中断");
        }
        System.out.println("线程 " + threadName + " 退出");
    }

    public static void main(String args[]) {
        // 创建Runnable实例
        RunnableExample R1 = new RunnableExample("线程-1");
        // 创建Thread实例,并将Runnable实例作为参数传入
        Thread t1 = new Thread(R1);

        RunnableExample R2 = new RunnableExample("线程-2");
        Thread t2 = new Thread(R2);

        // 启动线程
        t1.start();
        t2.start();
    }
}

《Java编程中第17章的并发基础探索》

17.2.2 继承Thread类

另一种创建线程的方式是继承Thread类,并重写其run()方法。接着创建该子类的实例并调用start()方法启动线程。

/**
 * 继承Thread类创建线程的示例
 */
public class ThreadExample extends Thread {
    private String threadName;

    public ThreadExample(String name) {
        threadName = name;
        System.out.println("创建线程: " + threadName);
    }

    // 重写run()方法,定义线程执行的任务
    public void run() {
        System.out.println("启动线程: " + threadName);
        try {
            for (int i = 4; i > 0; i--) {
                System.out.println("线程 " + threadName + ": " + i);
                // 让线程暂停一段时间
                Thread.sleep(50);
            }
        } catch (InterruptedException e) {
            System.out.println("线程 " + threadName + " 被中断");
        }
        System.out.println("线程 " + threadName + " 退出");
    }

    public static void main(String args[]) {
        // 创建线程实例
        ThreadExample t1 = new ThreadExample("线程-1");
        ThreadExample t2 = new ThreadExample("线程-2");

        // 启动线程
        t1.start();
        t2.start();
    }
}

《Java编程中第17章的并发基础探索》

两种方式的对比

实现Runnable接口 继承Thread类
能够继承其他类 无法再继承其他类
适合多个线程共享资源 资源共享需额外处理
代码结构更清晰,契合面向接口编程思想 代码相对简洁直接

17.2.3 主线程

每一个Java程序都有一个默认的主线程,也就是main()方法所在的线程。主线程是程序的入口,负责启动其他线程。

/**
 * 主线程示例
 */
public class MainThreadDemo {
    public static void main(String[] args) {
        // 获取当前线程(主线程)
        Thread mainThread = Thread.currentThread();

        System.out.println("主线程名称: " + mainThread.getName());
        System.out.println("主线程优先级: " + mainThread.getPriority());

        // 修改主线程名称
        mainThread.setName("MyMainThread");
        System.out.println("修改后主线程名称: " + mainThread.getName());

        // 启动一个新线程
        Thread childThread = new Thread(new Runnable() {
            public void run() {
                for (int i = 0; i < 5; i++) {
                    System.out.println("子线程运行中: " + i);
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        childThread.start();

        // 主线程执行任务
        for (int i = 0; i < 5; i++) {
            System.out.println("主线程运行中: " + i);
            try {
                Thread.sleep(150);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.out.println("主线程执行完毕");
    }
}

《Java编程中第17章的并发基础探索》

17.3 线程的状态与调度

17.3.1 线程的状态

Java中的线程具有以下几种状态,这些状态定义在Thread.State枚举中:

  1. 新建状态(New):线程对象已创建,但尚未调用start()方法
  2. 就绪状态(Runnable):线程已启动,正在等待CPU资源
  3. 运行状态(Running):线程正在执行
  4. 阻塞状态(Blocked):线程等待锁,暂时无法运行
  5. 等待状态(Waiting):线程等待其他线程的特定操作
  6. 超时等待状态(Timed Waiting):线程在指定时间内等待
  7. 终止状态(Terminated):线程已完成执行

线程状态转换示例

/**
 * 线程状态示例
 */
public class ThreadStateDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            public void run() {
                System.out.println("3. 线程运行中,状态: " + Thread.currentThread().getState());
                try {
                    // 线程进入超时等待状态
                    Thread.sleep(1000);

                    // 等待另一个线程的通知
                    synchronized (this) {
                        this.wait();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("6. 线程即将结束,状态: " + Thread.currentThread().getState());
            }
        });

        // 新建状态
        System.out.println("1. 线程创建后,状态: " + thread.getState());

        // 启动线程
        thread.start();
        Thread.sleep(100); // 等待线程启动
        System.out.println("2. 线程启动后,状态: " + thread.getState());

        // 等待线程进入超时等待状态
        Thread.sleep(200);
        System.out.println("4. 线程休眠中,状态: " + thread.getState());

        // 等待线程进入等待状态
        Thread.sleep(1000);
        System.out.println("5. 线程等待中,状态: " + thread.getState());

        // 唤醒等待的线程
        synchronized (thread) {
            thread.notify();
        }

        // 等待线程结束
        thread.join();
        System.out.println("7. 线程结束后,状态: " + thread.getState());
    }
}

《Java编程中第17章的并发基础探索》

17.3.2 线程的优先级与调度

Java线程具有优先级,范围在1到10之间,默认优先级为5。优先级较高的线程获取CPU资源的概率更大,但这并非意味着一定会先执行。

线程调度由Java虚拟机(JVM)和操作系统共同完成,Java提供了两种调度模型:

  • 抢占式调度:优先级高的线程能够抢占优先级低的线程的CPU资源
  • 时间片轮转:每个线程依次获取CPU时间片

    /*
    * 线程优先级示例
    /
    public class ThreadPriorityDemo {
    public static void main(String[] args) {
    // 创建三个线程
    Thread highPriority = new Thread(new Counter("高优先级线程"));
    Thread mediumPriority = new Thread(new Counter("中优先级线程"));
    Thread lowPriority = new Thread(new Counter("低优先级线程"));

        // 设置线程优先级
        highPriority.setPriority(Thread.MAX_PRIORITY); // 10
        mediumPriority.setPriority(Thread.NORM_PRIORITY); // 5
        lowPriority.setPriority(Thread.MIN_PRIORITY); // 1
    
        // 启动线程
        lowPriority.start();
        mediumPriority.start();
        highPriority.start();
    }
    
    static class Counter implements Runnable {
        private String name;
    
        public Counter(String name) {
            this.name = name;
        }
    
        public void run() {
            for (int i = 0; i < 5; i++) {
                System.out.println(name + ":" + i + ",优先级:" + Thread.currentThread().getPriority());
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    }

《Java编程中第17章的并发基础探索》

17.3.3 控制线程的结束

线程结束的方式有以下几种:

  1. 自然结束:线程的run()方法执行完毕
  2. 异常结束:线程执行过程中抛出未捕获的异常
  3. 中断结束:调用interrupt()方法中断线程

    /*
    * 线程结束控制示例
    /
    public class ThreadTerminationDemo {
    public static void main(String[] args) throws InterruptedException {
    // 创建一个可被中断的线程
    Thread interruptibleThread = new Thread(new InterruptibleTask());
    interruptibleThread.start();

        // 运行一段时间后中断线程
        Thread.sleep(2000);
        System.out.println("主线程:请求中断子线程");
        interruptibleThread.interrupt();
    
        // 等待线程结束
        interruptibleThread.join();
        System.out.println("主线程:子线程已结束");
    }
    
    static class InterruptibleTask implements Runnable {
        public void run() {
            try {
                while (!Thread.currentThread().isInterrupted()) {
                    System.out.println("子线程:正在执行任务...");
                    Thread.sleep(500); // 模拟任务执行
                }
                System.out.println("子线程:收到中断请求,准备结束");
            } catch (InterruptedException e) {
                System.out.println("子线程:在休眠中被中断");
                // 恢复中断状态
                Thread.currentThread().interrupt();
            } finally {
                System.out.println("子线程:执行清理工作");
            }
            System.out.println("子线程:已结束");
        }
    }
    

    }

《Java编程中第17章的并发基础探索》

注意:不建议使用stop()suspend()resume()方法来控制线程,这些方法已被标记为过时,可能会引发资源泄露或线程死锁等问题。

17.4 线程同步与对象锁

17.4.1 线程冲突与原子操作

当多个线程访问共享资源时,若不加以控制,可能会致使数据不一致,这便是线程冲突。

原子操作指的是不可分割的操作,要么全部执行,要么都不执行。Java提供了java.util.concurrent.atomic包来支持原子操作。

/**
 * 线程冲突示例
 */
public class ThreadConflictDemo {
    // 共享资源
    private static int count = 0;

    public static void main(String[] args) throws InterruptedException {
        // 创建两个线程,同时对count进行递增操作
        Thread thread1 = new Thread(new IncrementTask());
        Thread thread2 = new Thread(new IncrementTask());

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

        // 等待两个线程执行完毕
        thread1.join();
        thread2.join();

        // 预期结果是20000,但实际可能小于该值
        System.out.println("最终计数:" + count);
    }

    static class IncrementTask implements Runnable {
        public void run() {
            for (int i = 0; i < 10000; i++) {
                // 非原子操作:读取 -> 修改 -> 写入
                count++;
            }
        }
    }
}

《Java编程中第17章的并发基础探索》

上述代码中,count++并非原子操作,它包含读取count的值、将值加1、将结果写回count这三个步骤。当两个线程同时执行时,可能会导致计数不准确。

17.4.2 方法同步

运用synchronized关键字修饰方法,能够确保同一时间仅有一个线程执行该方法,从而避免线程冲突。

/**
 * 同步方法示例
 */
public class SynchronizedMethodDemo {
    // 共享资源
    private int count = 0;

    public static void main(String[] args) throws InterruptedException {
        SynchronizedMethodDemo demo = new SynchronizedMethodDemo();

        // 创建两个线程,同时对count进行递增操作
        Thread thread1 = new Thread(new IncrementTask(demo));
        Thread thread2 = new Thread(new IncrementTask(demo));

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

        // 等待两个线程执行完毕
        thread1.join();
        thread2.join();

        // 使用同步方法后,结果应当是20000
        System.out.println("最终计数:" + demo.count);
    }

    // 同步方法
    public synchronized void increment() {
        count++;
    }

    static class IncrementTask implements Runnable {
        private SynchronizedMethodDemo demo;

        public IncrementTask(SynchronizedMethodDemo demo) {
            this.demo = demo;
        }

        public void run() {
            for (int i = 0; i < 10000; i++) {
                demo.increment();
            }
        }
    }
}

《Java编程中第17章的并发基础探索》

对于

文章整理自互联网,只做测试使用。发布者:Lomu,转转请注明出处:https://www.it1024doc.com/13601.html

(0)
LomuLomu
上一篇 2025 年 9 月 18 日
下一篇 2025 年 9 月 18 日

相关推荐

  • 亲测可用pycharm激活码+全新pycharm破解教程合集

    免责声明:以下教程中涉及的 PyCharm 破解补丁、激活码均来自互联网公开分享,仅限个人学习研究,禁止商业用途。若条件允许,请支持正版! PyCharm 是 JetBrains 出品的一款跨平台 IDE,支持 Windows、macOS 与 Linux。本文将以 2025.2 版本为例,手把手演示如何借助破解补丁实现永久激活,解锁全部高级特性。 无论系统与…

    PyCharm激活码 2025 年 10 月 16 日
    16200
  • 2024 GoLand最新激活码,GoLand永久免费激活码2025-02-09 更新

    GoLand 2024最新激活码 以下是最新的GoLand激活码,更新时间:2025-02-09 🔑 激活码使用说明 1️⃣ 复制下方激活码 2️⃣ 打开 GoLand 软件 3️⃣ 在菜单栏中选择 Help -> Register 4️⃣ 选择 Activation Code 5️⃣ 粘贴激活码,点击 Activate ⚠️ 必看!必看! 🔥 获取最新激活…

    2025 年 2 月 9 日
    69100
  • PyCharm永久激活教程,2024破解教程,激活PyCharm

    本教程适用于PyCharm、PyCharm、DataGrip、Goland等,支持Jetbrains全家桶! 废话不多说,先给大家看一下最新PyCharm版本的破解截图,可以看到已经成功破解至2099年,激活效果非常好! 接下来,我会通过图文方式,详细讲解如何激活PyCharm至2099年。 无论你使用的是Windows、Mac还是Linux系统,无论你的P…

    2025 年 4 月 18 日
    53600
  • 永久免费申领datagrip激活码,实用破解教程

    声明:以下教程中的 DataGrip 破解补丁与激活码均搜集自互联网,仅供个人学习与研究,严禁商用。若涉及侵权,请联系删除。条件允许请支持正版! 先放一张成功截图镇楼:DataGrip 2025.2.1 已顺利激活到 2099 年,稳得一批! 下面用图文手把手演示如何给最新版 DataGrip 打补丁。 嫌折腾?官方正版全家桶低至 32 元/年,一键登录即用…

    2025 年 10 月 18 日
    5000
  • 深入解析 Java 多线程编程中的 Thread 类核心功能

    Java 平台的多线程编程能力主要依赖于 Thread 这个基础类。我们将全面剖析该类的重要特性与实用方法,并通过具体案例演示其应用场景。 一、线程的初始化与基础控制 在 Java 中,开发者可以通过以下两种主要途径创建新线程:1. #### 扩展 Thread 基类 class CustomThread extends Thread { public vo…

    2025 年 5 月 13 日
    22900

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信