《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 日

相关推荐

  • JAVA 图形界面编程 AWT篇(1)

    前言 为了应对JAVA课设,小编走上了java的图形界面编程的道路,通过博客分享自己的学习历程,并进行笔记的记录。 AWT(Abstract Window Toolkit)介绍 AWT(抽象窗口工具包)是 Java 最早的图形用户界面(GUI)框架之一,主要用于构建桌面应用程序的图形界面。最初在 JDK 1.0 版本中作为 Java GUI 的核心库引入,旨…

    未分类 2024 年 12 月 30 日
    41000
  • 2025年最新IDEA激活码及永久破解教程(支持2099年)

    适用于JetBrains全家桶的完美破解方案 今天给大家带来的是JetBrains系列开发工具(包括IDEA、PyCharm、DataGrip、Goland等)的终极破解教程。先看效果图,已经成功激活到2099年! 本教程将详细指导你如何获取最新IDEA激活码并完成永久破解,适用于所有操作系统和版本。 第一步:获取IDEA安装包 如果你已经安装过IDEA,可…

    IDEA破解教程 2025 年 8 月 12 日
    11900
  • 解决Java运行时版本不兼容导致的UnsupportedClassVersionError问题

    1、问题现象描述 在使用IntelliJ IDEA将Spring Boot项目打包为JAR文件后,通过命令行运行该JAR时出现以下错误提示:线程”main”中出现异常:java.lang.UnsupportedClassVersionError: com/automation/hweb/HwebApplication的类文件版本(61.0)超过了当前Java…

    2025 年 5 月 19 日
    25800
  • DataGrip 2025破解教程:最新永久激活码获取与使用方法

    引言 DataGrip是JetBrains公司开发的一款专业数据库管理工具,它为开发者提供了全面的数据库解决方案,支持MySQL、PostgreSQL、Oracle、MongoDB等多种主流数据库。这款工具拥有智能代码完成、错误检测和快速修复等功能,能够大幅提高数据库操作效率。不过,正版DataGrip需要付费使用,对于很多个人开发者来说费用不低。今天,我将…

    DataGrip破解教程 2025 年 4 月 27 日
    46900
  • 2025年最新DataGrip激活码及永久破解教程(支持2099年)

    前言 本教程适用于JetBrains系列开发工具,包含DataGrip、PyCharm、IDEA等常用IDE!先查看最新DataGrip版本成功破解到2099年的效果展示,让你完全放心使用!效果图展示 下面将详细介绍如何永久激活DataGrip至2099年。该方法同样兼容旧版本,无论你使用:- Windows/Mac/Linux操作系统- 任何DataGri…

    DataGrip激活码 2025 年 7 月 5 日
    16800

发表回复

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

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

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

关注微信