并发编程-01并发初窥

简介: 并发编程-01并发初窥

2019080611330380.jpg


引言


说来惭愧,一直没有系统的梳理过并发编程的知识,这次借着学习_Jimin_老师的《Java并发编程与高并发解决方案》课程的机会,结合以往工作中的使用,好好的梳理下并发编程与高并发的知识,形成一个较为完善的并发编程知识体系。


思维导图



20190216004125862.png

基础知识构建


20190216004542570.png


涉及的知识点一览


2019021600222758.png


高并发处理思路与手段一览



20190216002239979.png


并发初窥

概念


并发: 同时拥有两个或者多个线程,如果程序在单核处理器上运行多个线程将交替地换入或者换出内存,这些线程是 同时“存在”的,每个线程都处于执行过程中的某个状态,如果运行在多核处理器上,此时,程序中的每个线程都 将分配到一个处理器核上,因此可以同时运行。


高并发( High Concurrency): 是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指通过设计保证系统能够"同时并行处理"很多请求


  • 并发:多个线程操作相同的资源,保证线程安全,合理使用资源
  • 高并发:服务能同时处理很多请求,提高程序性能


并发问题模拟


首先说明如下代码是存在并发问题的,这里是为了抛出问题,后续给出解决办法.

其中用到的ExecutorService、Semaphore和CountDownLatch等先有个印象,后续深入探讨,更多说明见注释

Spring Boot搭建的工程,详见github ConcurrencyMaster

package com.artisan;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import lombok.extern.slf4j.Slf4j;
/**
 * 首先说明如下代码是存在并发问题的,这里是为了抛出问题,后续给出解决办法
 * 
 * 要求: 10000个请求,同一时间允许500个请求同时执行 即每次允许500个请求同时执行
 * 
 * 实现:使用线程池和信号量和countDownLatch模拟客户端总共发出了1万个请求,每次允许500个请求同时执行,观察一共执行了个多少个请求
 * 
 * @author yangshangwei
 *
 */
@Slf4j
public class CountCaculatorDemo {
  // 请求总数
  private static int clientTotal = 10000;
  // 同一时间执行的请求数
  private static int threadTotal = 1;
  // 计数标识
  private static int count = 0;
  public static void main(String[] args) throws InterruptedException {
    // 创建一个可缓存线程池,如果线程池长度超过实际需要,可灵活回收空闲线程,若无可回收的线程,则新建线程。
    ExecutorService executorService = Executors.newCachedThreadPool();
    // 信号量 同一时间允许threadTotal个请求同时执行 即初始化threadTotal个信号量
    final Semaphore semaphore = new Semaphore(threadTotal);
    // CountDownLatch是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行
    // 定义clientTotal个线程需要执行完,主线程才能继续执行
    final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
    // 创建clientTotal个线程,模拟clientTotal个请求
    for (int i = 0; i < clientTotal; i++) {
      // 执行一个线程 ,count加1
      executorService.execute(() -> {
        try {
          // 获取许可,获取许可后执行add方法, 在获得许可之前,一直将线程阻塞
          semaphore.acquire();
          add();
          // 释放许可,并将其返回给信号量
          semaphore.release();
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        // 【在循环内】每当一个线程完成了自己的任务后,计数器的值就会减1,这里指的是初始化CountDownLatch给定的clientTotal减一
        countDownLatch.countDown();
      });
    }
    // 主线程必须在启动其他线程后立即调用CountDownLatch.await()方法。
    // 这样主线程的操作就会在这个方法上阻塞,直到其他线程完成各自的任务。
    // 当全部线程都调用了countDown方法,count的值等于0,然后主线程就能通过await()方法,恢复执行自己的任务。
    countDownLatch.await();
    // 关闭线程池
    executorService.shutdown();
    // 打印总数
    log.info("执行总数:{}", count);
  }
  private static void add() {
    count++;
  }
}


执行多次,可以发现绝大部分情况下结果都不为1万,当然了也有可能为1万。


20190216101711130.png


如果将threadTotal 改为1 ,即同一时刻只允许一个线程执行,再次运行,无论如何运行多少次,结果都是10000。

说明多线程确实影响到了执行结果,后面继续将结合Java内存模型分析多线程是如何影响执行结果的。


代码


https://github.com/yangshangwei/ConcurrencyMaster


相关文章
|
2月前
|
存储 监控 算法
深入探究Java线程池:提升并发性能的利器
在当今高度并发的应用开发中,Java线程池作为一种广泛应用的并发编程技术,提供了一种优雅且高效的线程管理方案。本文深入探究Java线程池的相关技术,涵盖其核心概念、优势、常见类型(如FixedThreadPool、CachedThreadPool、SingleThreadExecutor、ScheduledThreadPool、ForkJoinPool及WorkStealingPool)、核心参数配置、异常处理与监控方法,以及性能调优的最佳实践,帮助读者更好地理解和应用线程池,从而提升并发性能。
|
3月前
|
Java 开发者
【编程高手必备】Java多线程编程实战揭秘:解锁高效并发的秘密武器!
【8月更文挑战第22天】Java多线程编程是提升软件性能的关键技术,可通过继承`Thread`类或实现`Runnable`接口创建线程。为确保数据一致性,可采用`synchronized`关键字或`ReentrantLock`进行线程同步。此外,利用`wait()`和`notify()`方法实现线程间通信。预防死锁策略包括避免嵌套锁定、固定锁顺序及设置获取锁的超时。掌握这些技巧能有效增强程序的并发处理能力。
26 2
|
4月前
|
Java 测试技术 容器
多线程编程基础与并发问题解决方案
多线程编程基础与并发问题解决方案
|
算法 安全 Java
深入理解多线程编程:并发世界的探险
在计算机编程领域,随着多核处理器的普及,多线程编程成为了一种常见的技术。多线程编程可以提高程序的性能,充分利用多核处理器的计算能力。然而,多线程编程并不容易,它引入了并发性和同步问题,需要开发者仔细思考和处理线程之间的竞争条件。本文将深入探讨多线程编程的概念、技术和最佳实践,帮助读者更好地应对并发编程挑战。
|
SQL 缓存 安全
【多线程】——java多线程编程核心读书总结
前段时间学习到多线程相关内容了,看了java多线程编程核心这本书,下面是小编对这本书的总结
|
算法 Java 调度
《多线程与高并发》读书笔记(一)
《多线程与高并发》读书笔记(一)
55 0
|
安全 算法 Java
【并发编程技术】「技术辩证分析」在并发编程模式下进行线程安全以及活跃性问题简析
【并发编程技术】「技术辩证分析」在并发编程模式下进行线程安全以及活跃性问题简析
76 0
【并发编程技术】「技术辩证分析」在并发编程模式下进行线程安全以及活跃性问题简析
|
存储 缓存 安全
Java并发编程系列之一并发理论基础
本系列文章开始Java并发编程的进阶篇的学习,为了初学者对多线程的初步使用有基本概念和掌握,前置知识会对一些基础篇的内容进行介绍,以使初学者能够丝滑入戏。
Java并发编程系列之一并发理论基础
|
存储 调度
阿里巴巴面试题- - -多线程&并发篇(三十三)
阿里巴巴面试题- - -多线程&并发篇(三十三)
|
缓存 监控 Java
阿里巴巴面试题- - -多线程&并发篇(三十一)
阿里巴巴面试题- - -多线程&并发篇(三十一)