线程

java并发简介

。_饼干妹妹 提交于 2020-03-06 18:51:25
  有的时候由于数据的同时访问,导致服务器不堪重负,这个时候就需要高并发的介入,这篇文章将会从线程,控制,监视器三个大方面来简单地介绍java的并发。 <!--原文请参考http://ifeve.com/java-concurrency-constructs/--> 线程 线程是一个独立执行的调用序列,同一个进程的线程在同一时刻共享一些系统资源(比如文件句柄等)也能访问同一个进程所创建的对象资源(内存资源)。java.lang.Thread对象负责统计和控制这种行为。 每个程序都至少拥有一个线程-即作为Java虚拟机(JVM)启动参数运行在主类main方法的线程。在Java虚拟机初始化过程中也可能启动其他的后台线程。这种线程的数目和种类因JVM的实现而异。然而所有用户级线程都是显式被构造并在主线程或者是其他用户线程中被启动。 这里对Thread类中的主要方法和属性以及一些使用注意事项作出总结。这些内容会在这本书(《Java Concurrency Constructs》)上进行进一步的讨论阐述。Java语言规范以及已发布的API文档中都会有更详细权威的描述。 构造方法 Thread类中不同的构造方法接受如下参数的不同组合: 一个Runnable对象,这种情况下,Thread.start方法将会调用对应Runnable对象的run方法。如果没有提供Runnable对象

黑马程序员----java基础----多线程

佐手、 提交于 2020-03-06 18:44:28
------ Java培训、Android培训、iOS培训、.Net培训 、期待与您交流! ------- 一、理解线程   进程:每个独立执行的程序称之为进程。   线程:线程就是一个进程内部的一条执行路径。   多线程:在java 虚拟机启动的时候会有一个 java.exe 的执行程序,也就是一个进程。该进程中至少有一个线程负责 java 程序的执行。而且这个线程运行的代码存在于 main 方法中。该线程称之为主线程。 JVM 启动除了执行一个主线程,还有负责垃圾回收机制的线程。像种在一个进程中有多个线程执行的方式,就叫做多线程。   线程和多线程区别如下:     ( 1 )每个进程都有独立的代码和数据空间,进程间的切换开销大。     ( 2 )同一进程内的多个线程共享相同的代码,每个线程有独立的运行栈和程序计数器,线程间的切换开销小。 二、创建线程的方式   创建线程共有两种方式:继承方式和实现方式(简单的说)。     1 、 继承方式       通过查找 java 的帮助文档 API ,我们发现 java 中已经提供了对线程这类事物的描述的类 ——Thread 类。这第一种方式就是通过继承 Thread 类,然后复写其 run 方法的方式来创建线程。     创建步骤:     (1),定义类继承 Thread 。     (2),复写 Thread 中的 run

C#多线程深入了解线程同步lock,Monitor,Mutex,同步事件和等待句柄 (上)

筅森魡賤 提交于 2020-03-06 18:31:13
来源CSDN博客: http://blog.csdn.net/mengsuo/archive/2008/12/06/3460106.aspx 本篇从Monitor,Mutex,ManualResetEvent,AutoResetEvent,WaitHandler的类关系图开始,希望通过本篇的介绍能对常见的线程同步方法有一个整体的认识,而对每种方式的使用细节,适用场合不会过多解释。让我们来看看这几个类的关系图: 1.lock关键字 lock是C#关键词,它将语句块标记为临界区,确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。方法是获取给定对象的互斥锁,执行语句,然后释放该锁。 MSDN上给出了使用lock时的注意事项通常,应避免锁定 public 类型,否则实例将超出代码的控制范围。常见的结构 lock (this)、lock (typeof (MyType)) 和 lock ("myLock") 违反此准则。 1)如果实例可以被公共访问,将出现 lock (this) 问题。 2)如果 MyType 可以被公共访问,将出现 lock (typeof (MyType)) 问题由于一个类的所有实例都只有一个类型对象(该对象是typeof的返回结果),锁定它,就锁定了该对象的所有实例

JUC

倾然丶 夕夏残阳落幕 提交于 2020-03-06 18:29:45
volatile 关键字和内存可见性: 内存可见性(Memory Visibility)是指当①某个线程正在使用对象状态,而②另一个线程在同时修改该状态,需要③确保当一个线程修改了对象 状态后,④其他线程能够看到发生的状态变化。----- 在程序运行的时候,jvm会为每个线程分配一块独立的缓存,其中有一块主存(存放着共享资源),线程一用于修改共享数据,main线程用于读共享数据, 当线程一要对主存中共享数据的值进行改变的时候,先把共享数据读到缓存中来,然后在修改值,修改完后,将修改好后的值写会到主存中去, 在将修改后的值写入主存中前,此时main线程从主存中的数据读取出来,按理来说是先线程一执行修改数据,在main线程读取修改后的数据, 由于在线程一共享数据写入主存之前就执行main线程中读取共享数据,所以导致main线程缓存中的值是修改前的值(按代码逻辑来说是修改后的), 此时main线程缓存中存放的值是修改前的值,当调用了比较底层的代码(例如while(true)),执行效率非常高,高到main线程没有机会再次去主存中 读取一次数据(就是线程一修改后的,即逻辑正确情况)。 内存可见性问题是,当多个线程操作共享数据时,彼此不可见(由于首先读取线程的数据(共享数据)是不符合代码逻辑的,再加上某个底层代码执行效率太高,读取线程无法再次去主存中获取最新数据)

dubbo知识点

假装没事ソ 提交于 2020-03-06 16:47:39
Dubbo Dubbo 是基于 netty 框架的,最大的特性就是 NIO Dubbo 在 spring 中的启动加载过程 在 spring 启动过程中,通过 applicationContext 去扫描配置项,扫描到 Dubbo.xml ,这个时候的 dubbo 就会初始化成一个 bean 对象,和其他 bean 本身没有区别,并且此时的 dubbo 还没有注册到注册中心暴露出去,只是一个最普通的 bean 存在 而一切顺利完成后,接下来就是暴露的过程。会调用 bean 中的导出 export 方法。然后找到所有的 provide 端中的服务,既我们的 dubbo:service ,然后把里面的配置项,包括接口名,接口路径等一系列参数封装成一个 url 然后找到我们 dubbo 。 Xml 中的 protocol 配置,一般这里都配的是 zk 以及 zk 的注册地址 address ,然后发送暴露,而暴露及时把这些 url 数据,封装成一个 key-value 的结构,然后存入一个全局的 currentHashMap 中 完成上述步骤后,暴露就完成了。接下来就是启动一个 netty 服务监听消费者消费; Consumer 和 provide 的通信过程 首先明确一点, dubbo 是采用 socket 长连接双工模式的,传输方式的单连接 NIO 异步传输。 客户端发起 dubbo

如何编写线程安全但可伸缩的类

落花浮王杯 提交于 2020-03-06 16:41:19
编写线程安全类时,主要问题是将数据分为多个独立的部分,并为这些部分选择合适的大小。如果部分太小,则我们的类不是线程安全的。如果部件太大,则该类不可扩展。 让我们看一个进一步说明这种情况的示例: 一个例子 假设我们要跟踪一个城市中有多少人。我们要支持两种方法,一种是获取当前居住在城市中的人数,另一种是将一个人从一个城市转移到另一个城市。因此,我们有以下界面: 由于我们要从多个线程并行使用此接口,因此必须选择实现此接口的选项。使用该类 java.util.concurrent. ConcurrentHashMap 或使用该类 java.util.HashMap 和一个锁。这是使用类的实现 java.util.concurrent.ConcurrentHashMap : 方法移动使用线程安全方法计算来减少源城市中的计数。然后,使用计算来增加目标城市中的计数。count方法使用线程安全方法 get 。 这是使用该类的实现 java.util.HashMap : 该方法 move 还使用该方法 compute 来增加和减少源城市和目标城市中的计数。仅在这一次,因为该 compute 方法不是线程安全的,所以两个方法都被同步块包围。该 count 方法 get 再次使用被同步块包围的方法。 两种解决方案都是线程安全的。 但是在使用的解决方案中 ConcurrentHashMap

JVM内存结构

空扰寡人 提交于 2020-03-06 16:22:27
java程序运行 java源文件,通过编译器,能够生产响应的.class文件,也就是字节码文件,而字节码文件通过java虚拟机中的解释器,编译成特定机器上的机器码 过程 : java源文件 ----> 编译器 ---->字节码文件 ----->JVM ----> 机器码 每一个平台的解释器是不同的,但是实现的虚拟机是相同的,这就是java能够跨平台的原因,当一个程序开始运行,这是虚拟机就开始实例化了,多个程序启动就会存在多个虚拟机实例。程序退出或者关闭,则虚拟机实例消亡,多个虚拟机实例之间数据不能共享 JVM内存区域 程序计数器(线程私有) 记录的是虚拟机字节码指令的地址,每个线程都有一个独立的程序计数器。 这个内存区域是唯一一个在虚拟机中没有任何OutOfMemoryError情况的区域 虚拟机栈(线程私有) 每一个方法在执行的时候都会创建一个栈帧,用于存储局部变量表,操作数栈,动态链接、方法返回值等信息。方法被调用,栈帧入栈,方法执行完毕,栈帧出栈。 栈帧 :随方法调用而创建,随方法结束而销毁,无论方法时正常完成还是异常抛出都算方法结束 操作数栈 :主要是方法中计算的部分,会进入操作数栈,计算的数值出栈,计算完成之后再将结果返回栈中。 本地方法区(线程私有) 区别于细腻基站为执行java方法服务,而本地方法区则为Native方法服务。 native方法

非原子的64位数据操作(long和double)

妖精的绣舞 提交于 2020-03-06 15:40:45
非volatile类型的64位数值变量,在JVM的内存模型中写入和读出都是原子操作,但是64位的long和double类型变量在JVM的内存模型中,是将64位的操作拆分乘2个32位的操作。当取出一个非volatile类型的long或者double变量时,如果有一个读线程和一个写线程,那么读线程有可能读出一个原来数值的高32位和一个更改过后的低32位的数值。 来源: https://www.cnblogs.com/dazhu123/p/12426317.html

垃圾回收集器

有些话、适合烂在心里 提交于 2020-03-06 13:57:46
1.垃圾收集器 G1收集器 首先将Java堆空间划分为一些大小相等的区域(region),每个区域都是虚拟机中的一段连续内存空间。G1通过执行并发的全局标记来确定整个Java堆空间中存活的对象。标记阶段完成后,G1就知道哪些区域基本上是空闲的。在回收内存时优先回收这些区域,这样通常都会回收相当数量的内存。这就是为什么它叫做Garbage-First的原因。顾名思义G1关注某些区域的回收和整理,这些区域中的对象很有可能被完全回收。而且G1使用了一个暂停时间预测模型使得暂停时间控制在用户指定的暂停时间内,并根据用户指定的暂停时间来选择合适的区域回收内存。它与前面的CMS收集器相比有两个显著的改进:一是G1收集器是基于“标记-整理”算法实现的收集器,也就是说它不会产生空间碎片,这对于长时间运行的应用系统来说非常重要。二是它可以非常精确地控制停顿,既能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒,具备了一些实时Java(RTSJ)的垃圾收集器的特征。 如果你的堆内存大于4G的话,那么G1会是要考虑使用的收集器。它是为了更好支持大于4G堆内存在JDK 7 u4引入的。G1收集器把堆分成多个区域,大小从1MB到32MB,并使用多个后台线程来扫描这些区域,优先会扫描最多垃圾的区域,这就是它名称的由来,垃圾优先Garbage First。

java高并发设计(一)--概念

可紊 提交于 2020-03-06 13:38:27
java高并发的核心,要了解并熟悉java的内存模型,并涉及相关的资源临界值。 java的内存模型围绕多线的技术要点:原子性,可见性,有序性。 原子性:原子性是指整个操作过的不可中断性,明确的说就是线程在执行过程中是顺序执行的,一旦开始操作将不受其他线程的干扰。比如对已经全局的变量进行复制的操作,每个线程都可以对其进行重新设值的操作,但是在多线程执行中,没有安全机制的情况下,不能保证其操作的原子性,有可能最终的结果不是你想看到的。所以最先的设置就是原子性。 可见性:可见性就是一个线程修改了某一个共享的变量或者资源,其他线程能够立即知道这个修改,可以参考java中的volatile关键字的效果。如果没有安全机制,一个全局变量的设置,在多线程执行下,一个线程对变量的修改对其他线程可能是不可见的,因为在多线程并发操作情况下,两个线程会同时修改该变量。 有序性:在单线程执行下,所有的代码操作计划都是顺序执行的,前面的代码总是优先执行。但是在多线程中,程序的执行顺序有可能就会出现混乱。 来源: oschina 链接: https://my.oschina.net/u/778766/blog/813196