当前位置:网站首页 > 技术博客 > 正文

java并发编程:核心方法与框架



所谓并发编程是指在一台处理器上 “同时” 处理多个任务。并发是在同一实体上的多个事件。多个事件在同一时间间隔发生。

并发编程,从程序设计的角度来说,是希望通过某些机制让计算机可以在一个时间段内,执行多个任务。从计算机 CPU 硬件层面来说,是一个或多个物理 CPU 在多个程序之间多路复用,提高对计算机资源的利用率。从调度算法角度来说,当任务数量多于 CPU 的核数时,并发编程能够通过操作系统的任务调度算法,实现多个任务一起执行。

对于一个 Java 程序员而言,能否熟练掌握并发编程是判断他优秀与否的重要标准之一。因为并发编程是 Java 语言中最为晦涩的知识点,它涉及操作系统、内存、CPU、编程语言等多方面的基础能力,更为考验一个程序员的内功。

并发编程有三大特性:

  • 原子性;
  • 可见性;
  • 有序性。

定义: 并发编程是指在一台处理器上 “同时” 处理多个任务。并发是在同一实体上的多个事件,多个事件在同一时间间隔发生

意义:开发者通过使用不同的语言,实现并发编程,充分的利用处理器(CPU)的每一个核,以达到最高的处理性能,提升服务器的资源利用率,提升数据的处理速度。

为了避免长时间的线程等待,我们一方面提升硬件指标(如多级高速缓存的诞生,这里不做讨论),另一方面引入了并发概念,充分的利用处理器(CPU)的每一个核,减少 CPU 资源等待的时间,以达到最高的处理性能。

Tips:操作系统分配的资源和调度对象其实就是 CPU 时间片。

b. 什么是线程?
官方定义: 线程是操作系统能够进行资源调度的最小单位,它被包含在进程之中,是进程中的实际运作单位,每个线程执行的都是进程代码的某个片段,特定的线程总是在执行特定的任务。

c. 线程与进程的区别?
诞生起源:先有进程,后有线程。进程由于资源利用率、公平性和便利性诞生,线程则是为了提高 CPU 的利用率、提高程序的执行效率而诞生。

概念:进程是资源分配的最小单位。 线程是程序执行的最小单位(线程是操作系统能够进行资源调度的最小单位,同个进程中的线程也可以被同时调度到多个 CPU 上运行),线程也被称为轻量级进程;

内存共享:默认情况下,进程的内存无法与其他进程共享(进程间通信通过 IPC 进行)。 线程共享由操作系统分配给其父进程的内存块。

串行:顺序执行,按步就搬。在 A 任务执行完之前不可以执行 B。

并行:同时执行,多管齐下。指两个或两个以上事件或活动在同一时刻发生。在多道程序环境下,并行性使多个程序同一时刻可在不同 CPU 核心上同时执行。

并发:穿插执行,减少等待。指多个线程轮流穿插着执行,并发的实质是一个物理 CPU 在若干道程序之间多路复用,其目的是提高有限物理资源的运行效率。
在这里插入图片描述

Java 内存模型(即 Java Memory Model,简称 JMM)本身是一种抽象的概念,并不真实存在,它描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式。

主内存(共享):Java 内存模型中规定所有变量都存储在主内存(堆区和方法区),主内存是共享内存区域,所有线程都可以访问。从上图中可以看到,Java 的并发内存模型与操作系统的 CPU 运行方式极其相似,这就是 Java 的并发编程模型。通过创建多条线程,并发的进行操作,充分利用系统资源,达到高效的并发运算。

关于工作内存和主内存,详见JVM运行时数据区。

  • 确定是否是多线程环境:多线程环境下操作共享变量需要考虑线程的安全性;
  • 确定是否有增删改操作:多线程环境下,如果对共享数据有增加,删除或者修改的操作,需要谨慎。为了保证线程的同步性,必须对该共享数据进行加锁操作,保证多线程环境下,所有的线程能够获取到正确的数据;
  • 多线程下的读操作:如果是只读操作,对共享数据不需要进行锁操作,因为数据本身未发生增删改操作,不会影响获取数据的准确性。

Thread 类的常用方法介绍:

方法 作用 start() 启动当前的线程,调用当前线程的 run () run() 通常需要重写 Thread 类中的此方法,将创建要执行的操作声明在此方法中。 currentThread() 静态方法,返回代码执行的线程。 getName() 获取当前线程的名字。 setName() 设置当前线程的名字。 sleep(long millitime) 让当前进程睡眠指定的毫秒数,在指定时间内,线程是阻塞状态。 isAlive() 判断进程是否存活。 wait() 线程等待。 notify() 线程唤醒。

Java 多线程有 3 种创建方式如下:

  • 方式一:继承 Thread 类的方式创建线程;
  • 方式二:实现 java.lang.Runnable 接口;
  • 方式三:实现 Callable 接口。
  • 步骤 1:继承 Thread 类 extends Thread;
  • 步骤 2:复写 run () 方法,run () 方法是线程具体逻辑的实现方法。

实例

 
  

Tips:由于 Java 是面向接口编程,且可进行多接口实现,相比 Java 的单继承特性更加灵活,易于扩展,所以相比方式一,更推荐使用方式二进行线程的创建。

  • 步骤 1:实现 Runnable 接口,implements Runnable;
  • 步骤 2:复写 run () 方法,run () 方法是线程具体逻辑的实现方法。

实例:

 
  

Tips:方式一与方式二的创建方式都是复写 run 方法,都是 void 形式的,没有返回值。但是对于方式三来说,实现 Callable 接口,能够有返回值类型。

  • 步骤 1:实现 Callable 接口,implements Callable;
  • 步骤 2:复写 call () 方法,call () 方法是线程具体逻辑的实现方法。

实例

 
  

首先确认,这并不是线程创建的第四种方式,先来看如何创建。

实例

 
  

从代码中可以看出,还是进行了一个 Runnable 接口的使用,所以这并不是新的 Thread 创建方式,只不过是通过方式二实现的一个内部类创建。

实验目的:对 Thread 的创建方式进行练习,巩固本节重点内容,并在练习的过程中,使用常用的 start 方法和 sleep 方法以及 线程的 setName 方法。

实验步骤

  • a.使用 Runnable 接口创建两条线程 :t1 和 t2;
  • b.设置线程 t1 和 t2 的线程名称分别为 “ThreadOne” 和 “ThreadTwo”;
  • c.线程 t1 执行完 run () 方法后,线程睡眠 5 秒;
  • d.线程 t2 执行完 run () 方法后,线程睡眠 1 秒。

实现:

 
  

                            

版权声明


相关文章:

  • maven官方仓库2025-07-21 21:01:01
  • html中的js怎么用2025-07-21 21:01:01
  • cve cwe区别2025-07-21 21:01:01
  • LINUX教程2025-07-21 21:01:01
  • 内部类为什么不能有静态方法2025-07-21 21:01:01
  • 数字图像处理实验报告完整版2025-07-21 21:01:01
  • 电脑cpu检测软件2025-07-21 21:01:01
  • 舅妈的妈妈我该怎么称呼2025-07-21 21:01:01
  • linux chroot命令2025-07-21 21:01:01
  • 企业部门gmp自检报告怎么写2025-07-21 21:01:01