热门面试题——多线程(源码案例详解)

简介: 热门面试题——多线程(源码案例详解)

问题一:写一个程序,证明AtomicInteger类比synchronized更高效

synchronized更高效
案例一

package duoxiancheng2;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author yeqv
 * @program A2
 * @Classname Ms4
 * @Date 2022/2/7 20:04
 * @Email w16638771062@163.com
 */
public class Ms4 {

    AtomicInteger n = new AtomicInteger(10000);
    int num = 10000;

    public static void main(String[] args) {

        var t = new Ms4();
        new Thread(t::minus, "T1").start();
        new Thread(t::minus, "T2").start();
        new Thread(t::minus, "T3").start();
        new Thread(t::minus, "T4").start();
        new Thread(t::minus, "T5").start();
        new Thread(t::minus, "T6").start();
        new Thread(t::minus, "T7").start();
        new Thread(t::minus, "T8").start();

    }

    void minus() {
        var a = System.currentTimeMillis();
        while (true) {
           /* if (n.get() > 0) {
                n.decrementAndGet();
                System.out.printf("%s 售出一张票,剩余%d张票。 %n", Thread.currentThread().getName(), n.get());
            } else {
                break;
            }*/
            synchronized (this) {
                if (num > 0) {
                    num--;
                    System.out.printf("%s 售出一张票,剩余%d张票。 %n", Thread.currentThread().getName(), num);
                } else {
                    break;
                }


            }


        }
        var b = System.currentTimeMillis();
        System.out.println(b - a);
    }
}

synchronized结果:
在这里插入图片描述
AtomicInteger结果:
在这里插入图片描述

问题二:写一个程序证明AtomXXX类的多个方法并不构成原子性

package demo16;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 写一个程序证明AtomXXX类的多个方法并不构成原子性
 */
public class T {
    AtomicInteger count = new AtomicInteger(0);

    void m() {
        for (int i = 0; i < 10000; i++) {
            if (count.get() < 100 && count.get() >= 0) { //如果未加锁,之间还会有其他线程插进来
                count.incrementAndGet();
            }
        }
    }

    public static void main(String[] args) {
        T t = new T();
        List<Thread> threads = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            threads.add(new Thread(t::m, "thread" + i));
        }
        threads.forEach(Thread::start);
        threads.forEach((o) -> {
            try {
                //join()方法阻塞调用此方法的线程,直到线程t完成,此线程再继续。通常用于在main()主线程内,等待其它线程完成再结束main()主线程。
                o.join(); //相当于在main线程中同步o线程,o执行完了,main线程才有执行的机会
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        System.out.println(t.count);
    }
}

**

问题三:写一个程序,在main线程中启动100个线程,100个线程完成后,主线程打印“完成”

package cn.thread;

import java.util.concurrent.CountDownLatch;

/**
 * 写一个程序,在main线程中启动100个线程,100个线程完成后,主线程打印“完成”
 *
 * @author webrx [webrx@126.com]
 * @version 1.0
 * @since 16
 */
public class T12 {
    public static void main(String[] args) {
        CountDownLatch latch = new CountDownLatch(100);
        for (int i = 0; i < 100; i++) {
            new Thread(() -> {
                String tn = Thread.currentThread().getName();
                System.out.printf("%s : 开始执行...%n", tn);
                System.out.printf("%s : 执行完成,程序结束。%n", tn);
                latch.countDown();
            }, "T" + i).start();
        }

        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("---------------------------------------");
        System.out.println("100个线程执行完了。");
        String tn = Thread.currentThread().getName();
        System.out.printf("%s : 执行完成,程序结束。%n", tn);
    }
}
相关文章
|
2月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
86 2
|
8天前
|
Java 数据库连接 Maven
最新版 | 深入剖析SpringBoot3源码——分析自动装配原理(面试常考)
自动装配是现在面试中常考的一道面试题。本文基于最新的 SpringBoot 3.3.3 版本的源码来分析自动装配的原理,并在文未说明了SpringBoot2和SpringBoot3的自动装配源码中区别,以及面试回答的拿分核心话术。
最新版 | 深入剖析SpringBoot3源码——分析自动装配原理(面试常考)
|
7天前
|
并行计算 算法 安全
面试必问的多线程优化技巧与实战
多线程编程是现代软件开发中不可或缺的一部分,特别是在处理高并发场景和优化程序性能时。作为Java开发者,掌握多线程优化技巧不仅能够提升程序的执行效率,还能在面试中脱颖而出。本文将从多线程基础、线程与进程的区别、多线程的优势出发,深入探讨如何避免死锁与竞态条件、线程间的通信机制、线程池的使用优势、线程优化算法与数据结构的选择,以及硬件加速技术。通过多个Java示例,我们将揭示这些技术的底层原理与实现方法。
60 3
|
2月前
|
存储 缓存 算法
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
本文介绍了多线程环境下的几个关键概念,包括时间片、超线程、上下文切换及其影响因素,以及线程调度的两种方式——抢占式调度和协同式调度。文章还讨论了减少上下文切换次数以提高多线程程序效率的方法,如无锁并发编程、使用CAS算法等,并提出了合理的线程数量配置策略,以平衡CPU利用率和线程切换开销。
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
|
2月前
|
缓存 监控 Java
Java线程池提交任务流程底层源码与源码解析
【11月更文挑战第30天】嘿,各位技术爱好者们,今天咱们来聊聊Java线程池提交任务的底层源码与源码解析。作为一个资深的Java开发者,我相信你一定对线程池并不陌生。线程池作为并发编程中的一大利器,其重要性不言而喻。今天,我将以对话的方式,带你一步步深入线程池的奥秘,从概述到功能点,再到背景和业务点,最后到底层原理和示例,让你对线程池有一个全新的认识。
56 12
|
27天前
|
存储 缓存 Java
Spring面试必问:手写Spring IoC 循环依赖底层源码剖析
在Spring框架中,IoC(Inversion of Control,控制反转)是一个核心概念,它允许容器管理对象的生命周期和依赖关系。然而,在实际应用中,我们可能会遇到对象间的循环依赖问题。本文将深入探讨Spring如何解决IoC中的循环依赖问题,并通过手写源码的方式,让你对其底层原理有一个全新的认识。
46 2
|
6天前
|
缓存 安全 Java
【JavaEE】——单例模式引起的多线程安全问题:“饿汉/懒汉”模式,及解决思路和方法(面试高频)
单例模式下,“饿汉模式”,“懒汉模式”,单例模式下引起的线程安全问题,解锁思路和解决方法
|
4月前
|
存储 缓存 Java
什么是线程池?从底层源码入手,深度解析线程池的工作原理
本文从底层源码入手,深度解析ThreadPoolExecutor底层源码,包括其核心字段、内部类和重要方法,另外对Executors工具类下的四种自带线程池源码进行解释。 阅读本文后,可以对线程池的工作原理、七大参数、生命周期、拒绝策略等内容拥有更深入的认识。
158 29
|
3月前
|
安全 Java
Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧
【10月更文挑战第20天】Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧,包括避免在循环外调用wait()、优先使用notifyAll()、确保线程安全及处理InterruptedException等,帮助读者更好地掌握这些方法的应用。
25 1
|
4月前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
502 37

相关实验场景

更多