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

相关推荐

  • 最新datagrip破解视频讲解+永久激活码配置

    免责声明:下文所述 DataGrip 2025.2.1 破解补丁与激活码均源自网络公开资源,仅限个人学习研究,禁止商业用途。若遇版权争议,请立即联系作者删除。条件允许时,请支持正版! 先放一张“战果”:DataGrip 已成功激活到 2099 年,爽歪歪! 下面用图文方式手把手带你完成最新版 DataGrip 的激活流程。 嫌折腾?官方正版全家桶低至 32 …

    DataGrip激活码 2025 年 11 月 12 日
    6600
  • IDEA破解工具使用小技巧|新手也能轻松上手!

    免责声明:下文所涉 IntelliJ IDEA 破解补丁、激活码均源自网络公开渠道,仅供个人学习与研究,禁止任何商业用途。若条件允许,请支持正版!如有侵权,请联系删除。 IntelliJ IDEA 是 JetBrains 家族的明星 IDE,跨 Windows、macOS、Linux 三端,功能全面。本教程将手把手演示如何借助破解补丁实现“永久激活”,解锁全…

    IDEA破解教程 2025 年 9 月 19 日
    15500
  • 『玩转Streamlit』–上传下载文件

    在Web应用中,文件的上传下载 是交互中不可缺少的功能。 因为在业务功能中,一般不会只有文字的交互,资料或图片的获取和分发是很常见的需求。 比如,文件上传 可让用户向服务器提交数据,如上传图片分享生活、提交文档用于工作协作等,丰富应用功能。 而文件下载 则使用户能获取服务器端的资源,像下载软件、报告等,提升用户对应用内容的获取能力,增强用户体验和应用实用性。…

    2024 年 12 月 30 日
    44500
  • IDEA激活教程:从下载到使用全流程图解

    本教程适用于 IDEA、PyCharm、DataGrip、Goland 等,支持 Jetbrains 全家桶! 废话不多说,先上最新 IDEA 版本破解成功的截图,如下,可以看到已经成功破解到 2099 年辣,舒服! 接下来,我就将通过图文的方式,来详细讲解如何激活 IDEA 至 2099 年。当然这个激活方法,同样适用于之前的旧版本!不管你是什么操作系统,…

    IDEA破解教程 2025 年 9 月 19 日
    12800
  • 2025年最新DataGrip激活码与永久破解教程(支持2099年)

    JetBrains数据库工具破解指南(含DataGrip/IDEA/PyCharm等) 先来看看成功破解后的效果展示,我的DataGrip已经顺利激活到2099年,可以完全免费使用! 下面将详细介绍DataGrip的完整破解流程,这个方法适用于所有操作系统和版本: Windows/Mac/Linux全平台支持 新旧版本通用 100%成功率保证 第一步:获取D…

    DataGrip激活码 2025 年 7 月 22 日
    22300

发表回复

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

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

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

关注微信