Java线程知识拾遗

知识回顾

进程与线程是常常被提到的两个概念。进程拥有独立的代码段、数据空间,线程共享代码段和数据空间,但有独立的栈空间。线程是操作系统调度的最小单位,通常一个进程会包含一个或多个线程。多线程和多进程都可以实现并发处理,如 nginx 使用多进程方式、tomcat 使用多线程方式、Apache 支持混合使用。在 C/C++ 等语言中可以同时使用多进程和多线程,而在 Java 中只能使用多线程。

在 Java 中,创建线程的唯一方式是创建 Thread 类的实例,调用实例的 start() 方法启动线程。

Java 线程实现

在 JDK 1.2 之前,Java 使用用户线程实现 Java 线程,在 JDK 1.2 及之后,Java 基于操作系统原生的线程模型实现 Java 线程。

使用用户线程( User Thread, UT ) 实现,是指线程建立在用户态空间,线程的建立、同步、调度与销毁都在用户态完成,进程与用户线程之间是1 : N 的对应关系。这种情况下,内核无法知道有多少个用户线程,实现较为复杂。

使用内核线程实现,是指基于轻量级进程( Light Weight Process, LWP ) 来实现线程。每个轻量级进程都有一个内核线程( Kernel-Level Thread, KLT ) 支持,与内核线程之间是 1 : 1 的对应关系。这种情况下,调度线程时可能需要在内核态和用户态之间进行切换。由于轻量级进程需要消耗内核资源,能够支持的线程数量是有限的。

如在 Windows 和 Linux 系统中,操作系统原生的线程模型是 1 : 1 的对应关系,对于 Sun JDK 来说,一个 Java 线程就对应着一个轻量级进程。

线程调度与状态

在 Java中线程的调度方式是抢占式调度,即由系统来负责各个线程的时间分配,并在线程使用完分配的时间后调度下一个线程。任何一个线程都不能独占 CPU 。Java 语言一共设置了 10 个线程优先级,当两个线程同时等待执行时,优先级高的先被调度。线程的优先级会被映射到操作系统原生线程上去,但各个操作系统的优先级划分不完全一样,因此两个优先级不同的 Java 线程在操作系统中执行时也可能处于相同的优先级。

Java 定义了 5 种线程状态,分别是新建 ( New )、运行 ( Running )、等待 ( Waiting )、限期等待 ( Timed Waiting )、阻塞 ( Blocked ) 和结束 ( Terminated )。任一时刻,线程都处于 5 种状态中的一种,并在各个状态之间切换,如图所示。

其中,各个状态含义如下:

新建:创建后未启动;

运行:对于 Java 来说,线程已经运行,但对于操作系统来说,可能在运行或等待;

等待:线程等待被其他线程唤醒,如调用了 wait、join 且没有指定超时时间;

限期等待:线程等待一段时间后被系统唤醒,如调用了 sleep、wait、join 并设置了超时时间;

阻塞:线程进入同步区域需要与其他线程协调同步,如需要进入 synchronized 区域但其他线程尚未退出此区域;

结束:run 方法执行完成后,线程结束。

虚拟机栈

在 Java 内存模型中,每个虚拟机线程都有自己私有的虚拟机栈。栈与线程同时创建,其中存储的是线程的栈帧 ( Stack Frame )。每个方法的调用,都对应着一个栈帧的入栈和出栈。在栈帧中,存储着局部变量表 ( Local Variable Table )、操作栈 ( Operand Stack )、动态连接 ( Dynamic Linking )、返回地址 ( Return Address ) 和其他附加信息。

线程的工作内存

在内存模型中,Java 要求所有的变量都必须存储在主内存中,每个线程拥有自己的工作内存。工作内存中保存了线程需要读写的变量的主内存的副本。线程对变量的读写操作都在工作内存中直接进行,并不会去操作主内存中的内容,主内存与工作内存的同步由虚拟机完成。不同线程不能访问彼此的工作内存,变量值的传递需要经过主内存才能完成。

Volatile 修饰的变量可以保证变量对所有线程可见,即某个线程修改变量后,其他线程总能立刻读到新值。即便如此,多线程并发时,对 volatile 变量进行自增自减操作也不能保证线程安全。

总结

线程在 Java 中只能通过创建 Thread 类的实例来创建。在 JDK 1.2 之后,Java 中的线程基于操作系统原生的线程模型来实现线程。线程的调度方式是抢占式调度,即由系统来负责各个线程的时间分配,并在线程使用完分配的时间后调度下一个线程。Java 定义了 5 种线程状态:新建、运行、等待、限期等待、阻塞和结束。

每个虚拟机线程都有自己私有的虚拟机栈。栈与线程同时创建,其中存储的是线程的栈帧。每个方法的调用,都对应着一个栈帧的入栈和出栈。每个线程拥有自己的工作内存,工作内存中保存了线程需要读写的变量的主内存的副本。线程对变量的读写操作都在工作内存中直接进行,并不会去操作主内存中的内容,主内存与工作内存的同步由虚拟机完成。

每周 3 篇学习笔记或技术总结,面向有一定基础的 Java 程序员,内容涉及 Java 进阶、虚拟机、MySQL、NoSQL、分布式计算、开源框架等多个领域。关注作者或微信公众号 backend-develop 第一时间获取最新内容。

原文地址:Java线程知识拾遗

时间: 2024-12-09 13:42:13

Java线程知识拾遗的相关文章

java基础知识拾遗(四)

1.Runnable对象 启动线程:(new Thread(new MyRunnable()).start() 2.jsp中<%@ page language="java" import="java.util.*" errorPage="error.jsp" isErrorPage="false" %>  改页面不能使用exception对象 3.枚举 enum AccountType { SAVING, FIXE

java基础知识拾遗(二)

1.finally public static int func (){ try{ return 1; }catch (Exception e){ return 2; }finally { return 3; } } public static int func (){ try{ throw new Exception(); }catch (Exception e){ return 2; }finally { return 3; } } 返回值均为3;这表明finally块的代码会在正常retu

java基础知识拾遗(三)

1.类加载 bootstrap classloader -引导(也称为原始)类加载器,它负责加载Java的核心类. extension classloader -扩展类加载器,它负责加载JRE的扩展目录(JAVA_HOME/jre/lib/ext或者由java.ext.dirs系统属性指定的)中JAR的类包. system classloader -系统(也称为应用)类加载器,它负责在JVM被启动时,加载来自在命令java中的-classpath或者java.class.path系统属性 或者

java线程及操作实例,线程池简单例子

java io.集合.线程.字符串.gc.jvm可谓是java中的最基本的知识,尤其是线程操作复杂,相应难懂,要想java基础知识扎实,上面提到的几个方面的知识点都要精通,这样方可以称自己掌握java方面基础知识. 总结一下java线程知识,平时接触过线程,尤其是在android开发中,线程可谓是无处不在,稍有不注意就会报错.在java中线程也是无处不在,main就是一个线程,只不过被包装好了,一般接触不到. 我的无数次的复习经历告诉我,学习知识最快,最深刻的方法就是从解题开始,不要先看概念,遇

计算机底层知识拾遗(二)深入理解进程和线程

关于进程和线程,大家总是说的一句话是"进程是操作系统分配资源的最小单元,线程是操作系统调度的最小单元".这句话理论上没问题,我们来看看什么是所谓的"资源"呢. 什么是计算机资源 经典的冯诺依曼结构把计算机系统抽象成 CPU + 存储器 + IO,那么计算机资源无非就两种: 1. 计算资源 2. 存储资源 CPU是计算单元,单纯从CPU的角度来说它是一个黑盒,它只对输入的指令和数据进行计算,然后输出结果,它不负责管理计算哪些"指令和数据". 换句话

java基础知识回顾之java Thread类学习(三)--java线程实现常见的两种方式实现好处:

总结:实现Runnable接口比继承Thread类更有优势: 1.因为java只能单继承,实现Runnable接口可以避免单继承的局限性 2.继承Thread类,多个线程不能处理或者共享同一个资源,但是实现Runnable接口可以处理同一个资源. 下面我们做个测试:验证下.车站的售票系统售票的例子,车站的各个售票口相当于各个线程,我们先使用第一种方法几继承Thread类的方式实现: 代码如下: package com.lp.ecjtu.Thread; /** * * @author Admini

Java线程基础知识(状态、共享与协作)

1.基础概念 CPU核心数和线程数的关系 核心数:线程数=1:1 ;使用了超线程技术后---> 1:2 CPU时间片轮转机制 又称RR调度,会导致上下文切换 什么是进程和线程 进程:程序运行资源分配的最小单位,进程内部有多个线程,会共享这个进程的资源 线程:CPU调度的最小单位,必须依赖进程而存在. 澄清并行和并发 并行:同一时刻,可以同时处理事情的能力 并发:与单位时间相关,在单位时间内可以处理事情的能力 高并发编程的意义.好处和注意事项 好处:充分利用cpu的资源.加快用户响应的时间,程序模

java基础知识回顾之java Thread类学习(八)--java多线程通信等待唤醒机制经典应用(生产者消费者)

 *java多线程--等待唤醒机制:经典的体现"生产者和消费者模型 *对于此模型,应该明确以下几点: *1.生产者仅仅在仓库未满的时候生产,仓库满了则停止生产. *2.消费者仅仅在有产品的时候才能消费,仓空则等待. *3.当消费者发现仓储没有产品可消费的时候,会唤醒等待生产者生产. *4.生产者在生产出可以消费的产品的时候,应该通知等待的消费者去消费. 下面先介绍个简单的生产者消费者例子:本例只适用于两个线程,一个线程生产,一个线程负责消费. 生产一个资源,就得消费一个资源. 代码如下: pub

java基础知识回顾之java Thread类学习(七)--java多线程通信等待唤醒机制(wait和notify,notifyAll)

1.wait和notify,notifyAll: wait和notify,notifyAll是Object类方法,因为等待和唤醒必须是同一个锁,不可以对不同锁中的线程进行唤醒,而锁可以是任意对象,所以可以被任意对象调用的方法,定义在Object基类中. wait()方法:对此对象调用wait方法导致本线程放弃对象锁,让线程处于冻结状态,进入等待线程的线程池当中.wait是指已经进入同步锁的线程,让自己暂时让出同步锁,以便使其他正在等待此锁的线程可以进入同步锁并运行,只有其它线程调用notify方