《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版) 周志明》 - 第12章代码示例

这篇具有很好参考价值的文章主要介绍了《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版) 周志明》 - 第12章代码示例。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景

        最近在看《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版) 周志明》这本书,书中有些代码示例是为了让读者理解作者表达的意思,但不是完整的代码示例,所以针对这些不完整的代码,自己动手写出完整的代码示例。

说明

(1)在看这本书的同学,可以拿我这里的示例代码做个参考,并欢迎提出意见和建议;

(2)示例的标号,是和书中的代码示例标号相对应的。

第12章 - 代码

示例:12-1

/**
 * 这个程序演示的是:《深入理解JVM》(周志明 第三版) 代码清党12-1 volatile运算
 * 
 * volatile关键字只能保证可见性,并不能保证原子性(和有序性)
 * 因为程序输出的结果有不等于200000的情况发生
 */
public class VolatileTest_12_1 {


    public static volatile int race = 0;


    public static void increase() {
        race++;
    }

    private static final int THREAD_COUNT = 20;

    public static void main(String[] args) {
        Thread[] threads = new Thread[THREAD_COUNT];
        for (int i = 0; i < THREAD_COUNT; i++) {
            threads[i] = new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 10000; i++) {
                        increase();
                    }
                }
                    
            });
            threads[i].start();
        }

        // 等待所有累加线程都结束
        for (Thread thread : threads) {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
        System.out.println(race);
    }
}

示例:12-1的解决方式一

/**
 * 这个程序演示的是:
 *
 * volatile关键字只能保证可见性,并不能保证原子性(和有序性)
 * 
 * 针对这个程序,想要保证并发执行的结果符合预期,可以使用 synchronized关键字实现(但是这种实现方式是重量级的实现,效率较低)
 */
public class VolatileTest_12_1_Solution_1 {

    public static volatile int race = 0;
    
    public static void increase() {
        race++;
    }

    private static final int THREAD_COUNT = 20;

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        Thread[] threads = new Thread[THREAD_COUNT];
        for (int i = 0; i < THREAD_COUNT; i++) {
            threads[i] = new Thread(new Runnable() {
                @Override
                public void run() {
                    synchronized (VolatileTest_12_1_Solution_1.class) {
                        for (int i = 0; i < 10000; i++) {
                            increase();
                        }
                    }

                }
            });
            threads[i].start();
        }

        // 等待所有累加线程都结束
        for (Thread thread : threads) {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(race);
        long end = System.currentTimeMillis();
        System.out.println((end - start));
    }
}

示例:12-1的解决方式二

import java.util.concurrent.atomic.AtomicInteger;

/**
 * 这个程序演示的是:
 * <p>
 * volatile关键字只能保证可见性,并不能保证原子性(和有序性)
 * <p>
 * 针对这个程序,想要保证并发执行的结果符合预期,可以使用 synchronized关键字实现(但是这种实现方式是重量级的实现,效率较低)
 */
public class VolatileTest_12_1_Solution_2 {

    //public static volatile int race = 0;

    //public static void increase() {
    //    race++;
    //}

    public static AtomicInteger race = new AtomicInteger(0);

    public static void increase() {
        race.incrementAndGet(); // 原子操作的方法(底层使用CAS指令实现)
    }

    private static final int THREAD_COUNT = 20;

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        Thread[] threads = new Thread[THREAD_COUNT];
        for (int i = 0; i < THREAD_COUNT; i++) {
            threads[i] = new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 10000; i++) {
                        increase();
                    }
                }
            });
            threads[i].start();
        }

        // 等待所有累加线程都结束
        for (Thread thread : threads) {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(race);
        long end = System.currentTimeMillis();
        System.out.println((end - start));
    }
}

示例:12-3

/**
 * 
 * volatile的使用场景
 * 
 * (书中原话)
 * 而在像代码清单12-3所示的这类场景中就很适合使用volatile变量来控制并发,当shutdown()方法被调用时,
 * 能保证所有线程中执行的doWork()方法都立即停下来。
 */
public class VolatileTest_12_3 {

    private static final int THREADS_COUNT = 3;

    public static void main(String[] args) throws InterruptedException {

        MyTask myTask = new MyTask();
        Thread[] threads = new Thread[THREADS_COUNT];
        for (int i = 0; i < THREADS_COUNT; i++) {
            threads[i] = new Thread(myTask, "t"+(i+1));
            threads[i].start();
        }
        Thread.sleep(500);
        myTask.shutdown();
    }
}


class MyTask implements Runnable {

    private volatile boolean shutdownRequested;

    public void shutdown() {
        System.out.println(Thread.currentThread().getName()+"---->");
        shutdownRequested = true;
    }

    @Override
    public void run() {
        while (!shutdownRequested) {
            //try {
            //    Thread.sleep(500);
            //} catch (InterruptedException e) {
            //    throw new RuntimeException(e);
            //}
            System.out.println(Thread.currentThread().getName() + " --- do something...");
        }
    }
}

示例:12-4

import lombok.extern.slf4j.Slf4j;

/**
 * 需求:模拟一个A线程用来读取配置信息,另一个B线程等待A线程把配置信息读取完成后执行后续任务,
 * 其中线程A在读取完成配置信息后会把一个flag标志位由false变为true, B线程读取到这个flag标志位为true后,才开始执行
 */
@Slf4j
public class VolatileTest_12_4 {
    
    public static void main(String[] args) {
        
        // 创建配置信息对象
        Configuration configuration = new Configuration();
        
        Thread threadA = new Thread("Thread-A"){
            @Override
            public void run() {
                // 模拟读取配置信息的耗时操作
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                // 读取完配置信息后,将其标志位改为true
                configuration.setConfigLoaded(true);
                log.info("Thread-A: Configuration reading completed.");          
            }
        };

        Thread threadB = new Thread("Thread-B"){
            @Override
            public void run() {
                // 等待标志位为true
                while (!configuration.isConfigLoaded()){
                    // 在标志位为false时,线程Thread-B什么都不做
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    log.info("no no no no...");
                }
                
                log.info("Thread-B: Start executing subsequent tasks.");
            }
        };
        
        threadA.start();
        threadB.start();
    }
}

// 配置类
class  Configuration{
    private volatile boolean configLoaded = false;

    public boolean isConfigLoaded() {
        return configLoaded;
    }

    public void setConfigLoaded(boolean configLoaded) {
        this.configLoaded = configLoaded;
    }
}

未完待续...文章来源地址https://www.toymoban.com/news/detail-815474.html

到了这里,关于《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版) 周志明》 - 第12章代码示例的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [AIGC] 深入理解 Java 虚拟机(JVM)的垃圾回收

    一、是什么 Java 虚拟机(JVM)的垃圾回收(Garbage Collection)是一种自动内存管理机制,用于释放不再使用的对象所占用的内存空间。垃圾回收的目标是回收那些不再被程序引用的对象,以避免内存泄漏和内存溢出等问题。 二、为什么需要垃圾回收 在 Java 程序中,对象的创建

    2024年02月21日
    浏览(53)
  • [AIGC] 利用 chatgpt 深入理解 Java 虚拟机(JVM)

    Java 虚拟机(JVM)是 Java 编程语言的核心运行环境,它负责解释和执行 Java 字节码。它是 Java 程序能够跨平台运行的关键,因为不同的操作系统和硬件平台都有自己的指令集和体系结构,而 JVM 则提供了一个统一的运行环境,使得 Java 程序可以在不同的平台上无需修改就能运行

    2024年02月22日
    浏览(48)
  • “深入理解Java虚拟机(JVM):背后的工作原理解析“

    标题:深入理解Java虚拟机(JVM):背后的工作原理解析 摘要:本文将深入探讨Java虚拟机(JVM)的工作原理,包括内存管理、垃圾回收、即时编译器等关键概念,以及如何优化代码以提高性能。通过示例代码和详细解释,读者将对JVM的底层原理有更深入的理解。 正文: 一、

    2024年02月12日
    浏览(50)
  • jvm复习,深入理解java虚拟机一:运行时数据区域

            程序计数器 (Program Counter Register) 它是程序控制流的指示器,简单来说,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器          Java虚拟机栈 (Java Virtual Machine Stack)也是线程私有的,它的生命周期 与线程相同。虚拟机栈描述

    2024年01月22日
    浏览(49)
  • “深入探索JVM内部机制:理解Java虚拟机的运行原理“

    标题:深入探索JVM内部机制:理解Java虚拟机的运行原理 摘要:本篇博客将深入探索Java虚拟机(JVM)的内部机制,帮助读者理解JVM的运行原理。我们将介绍JVM的组成结构,包括类加载器、运行时数据区域和执行引擎,并通过示例代码解释这些概念的具体应用。 正文: 一、J

    2024年02月11日
    浏览(47)
  • “深入探究JVM内部机制:理解Java虚拟机的工作原理“

    标题:深入探究JVM内部机制:理解Java虚拟机的工作原理 摘要:本文将深入分析Java虚拟机(JVM)的工作原理,包括类加载、内存管理、垃圾回收和即时编译等方面。通过详细解释这些概念,并给出示例代码,帮助读者更好地理解JVM内部的工作机制。 正文: 一、类加载 类加载

    2024年02月12日
    浏览(50)
  • “深入剖析JVM内部机制:理解Java虚拟机的工作原理“

    标题:深入剖析JVM内部机制:理解Java虚拟机的工作原理 介绍: Java虚拟机(JVM)是Java语言的核心组件,负责将Java源代码转换为可以在计算机上运行的机器码。了解JVM的内部机制对于开发人员来说非常重要,因为它可以帮助我们更好地理解Java程序的运行行为和性能优化。本文

    2024年02月12日
    浏览(46)
  • “深入解析JVM内部机制:理解Java虚拟机的工作原理“

    标题:深入解析JVM内部机制:理解Java虚拟机的工作原理 摘要:本文将深入探讨Java虚拟机(JVM)的内部机制,解释其工作原理。我们将讨论JVM的组成部分、类加载过程、运行时数据区域以及垃圾回收机制。此外,还将通过示例代码来说明JVM的内部工作机制。 正文: JVM的组成

    2024年02月13日
    浏览(50)
  • “深入探索JVM内部机制:理解Java虚拟机的工作原理“

    标题:深入探索JVM内部机制:理解Java虚拟机的工作原理 摘要:本文将深入探索Java虚拟机(JVM)的内部机制,讲解JVM的工作原理,并通过示例代码帮助读者更好地理解JVM的工作过程。 正文: 一、JVM概述 Java虚拟机(JVM)是Java程序的运行环境,它负责将Java字节码转换为机器码

    2024年02月11日
    浏览(67)
  • 深入理解 Java 多线程、Lambda 表达式及线程安全最佳实践

    线程使程序能够通过同时执行多个任务而更有效地运行。 线程可用于在不中断主程序的情况下在后台执行复杂的任务。 创建线程 有两种创建线程的方式。 扩展Thread类 可以通过扩展Thread类并覆盖其run()方法来创建线程: 实现Runnable接口 另一种创建线程的方式是实现Runnable接口

    2024年03月15日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包