ThreadLocal

ThreadLocal ThreadLocal 是什么 弱引用 避免内存溢出的操作 开放地址法解决 hash 冲突 各种内部类 线程本地变量有时会简写为 TLV, Thread Local Variables ThreadLocal 是什么 ThreadLocal 是线程的局部变量, 也就是说这个变量是线程独有的。 通常情况下, 我们创建的变量是可以被任何一个线程访问并修改的。而使用 ThreadLocal 创建的变量只能被当前线程访问, 其他线程则无法访问和修改。 变量是同一个, 但是每个线程都使用同一个初始值, 也就是使用同一个变量的一个新的副本, 这种情况下 TreadLocal 就非常有用。 应用场景: 当很多线程需要多次使用同一个对象, 并且需要该对象具有相同初始值的时候, 最适合使用TreadLocal。 事实上,从本质上讲,就是每个线程都维持一个 MAP,而这个map的key就是TreadLocal,而值就是我们set的那个值,每次线程在get的时候,都从自己的变量中取值,既然从自己的变量中取值,那就肯定不存在线程安全的问题。总体来讲,TreadLocal这个变量的状态根本没有发生变化。它仅仅是充当了一个key的角色,另外提供给每一个线程一个初始值。如果允许的话,我们自己就能实现一个这样的功能,只不过恰好JDK就已经帮助我们做了这个事情。 使用TreadLocal维护变量时, TreadLocal为每个使用该变量的线程提供独立地变量副本, 所以每一个线程都可以独立地改变自己的副本,而不会影响其他线程所对应的副本。从线程的角度看,目标变量对象是线程的本地变量,这也是类名中Local所需要表达的意思。 TreadLocal的四个方法 void set(Object val),设置当前线程的线程局部变量的值 Object get () 返回当前线程所对用的线程局部变量。 void remove() 将当前线程局部变量的值删除,目的是为了减少内存的占用,线程结束后,局部变量自动被GC Object initValue() 返回该线程局部变量的初始值,使用protected修饰,显然是为了让子类覆盖而设计的。 ThreadLocalMap HashMap 的数据结构是数组+链表 ThreadLocalMap的数据结构仅仅是数组 HashMap 是通过链地址法解决 hash 冲突的问题 ThreadLocalMap 是通过开放地址法来解决 hash 冲突的问题 HashMap 里面的Entry 内部类的引用都是强引用 ThreadLocalMap里面的Entry 内部类中的key 是弱引用,value 是强引用 对象存放在哪里 在Java中, 栈内存归属于单个线程, 每个线程都会有一个栈内存,其存储的变量只能在其所属线程中可见,即栈内存可以理解成线程的私有内存。而堆内存中的对象对所有线程可见。堆内存中的对象可以被所有线程访问。 ...

2017-03-24 · 3 min · 597 words · -

spring restful, spring boot, maven,gradle

spring restful, spring boot, maven,gradle spring-boot-starter-parent <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.2</version> </parent> 表示当前pom文件从spring-boot-starter-parent继承下来,在spring-boot-starter-parent中提供了很多默认的配置,这些配置可以大大简化我们的开发。 Parent Poms Features 通过继承spring-boot-starter-parent,默认具备了如下功能: Java版本 (Java8) 源码的文件编码方式 (UTF-8) 依赖管理 打包支持 动态识别资源 识别插件配置 识别不同的配置,如:application-dev.properties 和 application-dev.yml 以上继承来的特性有的并非直接继承自spring-boot-starter-parent,而是继承自spring-boot-starter-parent的父级spring-boot-dependencies 需要特别说明的是,application-dev.properties 和 application-dev.yml支持spring风格的占位符(${…​}),但是Maven项目把对占位符的支持改为(@..@),可以通过设置Maven属性resource.delimiter来重置回去。 继承spring-boot-starter-parent后,大大简化了我们的配置,它提供了丰富的常用的默认的依赖的版本定义,我们就不需要再次指定版本号: <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> 假设我们需要定制自己的版本号,可以通过下面的方式重写: spring-boot-starter-web <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> Spring Web Starter使用Spring MVC,REST和Tomcat作为默认的嵌入式服务器 Spring Boot还支持另外两个嵌入式服务器: Jetty Server Undertow Server gradle bootRun run with env java -jar xxx.jar --spring.profiles.active=prod https://tengj.github.io/2017/02/26/springboot1/ ...

2017-02-22 · 1 min · 179 words · -

jcmd

jcmd New Features in JDK7 update 4 JRockit command line utility JRCMD (JRockit Command). JRCMD was a command line tool to enumerate the Java processes running on the local machine, and to send commands (referred to as “Diagnostic Commands”) to them. JRCMD has been renamed JCMD (Java Command). jcmd用于向正在运行的JVM发送诊断信息请求,是从JDK1.7开始提供可以说是jstack和jps的结合体 #查看java进程, jcmd 不带参数时默认列出所有java进程。 jcmd [-l] # help jcmd PID help # For more information about a specific command, 查看某一个命令的帮助信息。 jcmd PID help ManagementAgent.start #打印线程栈 jcmd PID Thread.print # 打印线程栈 + 锁信息 jcmd PID Thread.print -l #打印 Thread.print 命令的帮助信息 kill -3 <PID> #仅限Linux平台 jstack <PID> # jcmd提供了输出HPROF格式的堆dump接口。运行jcmd GC.heap_dump 即可。 # 注意这里的FILENAME是相对于运行中的jvm目录来说的,因此避免找不到dump的文件,这里推荐使用绝对路径。此外,也建议使用.hprof作为输出文件的扩展名。 # hprof文件分析工具: NetBeans, Elipse的MAT,jhat jcmd PID GC.heap_dump /tmp/dump.hprof # 打印出堆直方图(同时也打印出存活对象的数目) jcmd <PID> GC.class_histogram #启动参数 jcmd <PID> VM.command_line #查看JVM参数, 如: -XX:MaxHeapSize, -XX:MaxNewSize jcmd <PID> VM.flags #uptime jcmd <PID> VM.uptime # 查看系统变量 jcmd <PID> VM.system_properties jcmd [ pid | main-class ] command [ arguments ] ...

2017-02-06 · 1 min · 213 words · -

java maven 可执行 jar/ executable jar, maven-assembly-plugin

java maven 可执行 jar/ executable jar, maven-assembly-plugin 在pom中加入 maven-assembly-plugin <project> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.3.0</version> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>com.wiloon.java.lock.TestFutex</mainClass> </manifest> </archive> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project> mvn clean package assembly:single # 如果没执行过 mvn package 会报错: Cannot include project artifact: com.wiloon.java:pingd-java:jar:1.0-SNAPSHOT; it doesn't have an associated file or directory. java -jar target/pingd-java-1.0-SNAPSHOT-jar-with-dependencies.jar

2016-12-16 · 1 min · 63 words · -

java 队列, Queue, Deque

java 队列, Queue, Deque 名称 deque 是 “double ended queue (双端队列)” 的缩写, 通常读为 “deck”。 大多数 Deque 实现对于它们能够包含的元素数没有固定限制, 但此接口既支持有容量限制的双端队列, 也支持没有固定大小限制的双端队列. ArrayBlockingQueue 基于数组的阻塞队列 http://wiloon.com/ArrayBlockingQueue LinkedBlockingQueue 链表结构组成的有界阻塞队列。 PriorityBlockingQueue 支持优先级排序的无界阻塞队列。 DelayQueue 一个使用优先级队列实现的无界阻塞队列。 SynchronousQueue 不存储元素的阻塞队列 LinkedTransferQueue 一个由链表结构组成的无界阻塞队列。 LinkedBlockingDeque 一个由链表结构组成的双向阻塞队列。 https://blog.wiloon.com/?p=8256 ConcurrentLinkedDeque 非阻塞线程安全列表 ConcurrentLinkedQueue ConcurrentLinkedQueue 是一个基于链接节点的无界线程安全队列 http://blog.wiloon.com/?p=11670 Queue add 增加一个元索 如果队列已满, 则抛出一个 IIIegaISlabEepeplian 异常 offer 添加一个元素并返回 true 如果队列已满, 则返回 false put 添加一个元素 如果队列满, 则阻塞 remove 移除并返回队列头部的元素如果队列为空, 则抛出一个 NoSuchElementException 异常 poll 移除并返回队列头部的元素如果队列为空,则返回 null take 移除并返回队列头部的元素 如果队列为空,则阻塞 element 返回队列头部的元素 如果队列为空,则抛出一个 NoSuchElementException 异常 ...

2016-05-08 · 2 min · 268 words · -

maven依赖本地非repository中的jar包

maven 依赖本地非 repository 中的 jar 包 maven依赖本地非repository中的jar包 http://www.cnblogs.com/piaolingxue/archive/2011/10/12/2208871.html 博客分类: MAVEN 今天在使用maven编译打包一个web应用的时候,碰到一个问题: 项目在开发是引入了依赖jar包,放在了WEB-INF/lib目录下,并通过buildpath中将web libariary导入。 在eclipse中开发没有问题,但是使用maven编译插件开始便宜总是报找不到WEB-INF/lib这个jar包中的类。 显然实在编译的时候WEB-INF/lib并没有配置到maven-complier-plugin插件src目录中去, 于是将这个目录添加进去,还是不好使。无赖,先把这个jar包安装到本地库中,然后添加dependency。 后来google了下,发现maven提供了scope为system的依赖,文档的原文如下: system This scope is similar to provided except that you have to provide the JAR which contains it explicitly. The artifact is always available and is not looked up in a repository. 这样就可以添加dependency而不需要再将WEB-INF/lib目录下的jar包安装到本地库中了。 具体配置录下: <dependency> <groupId>org.apache</groupId> <artifactId>test</artifactId> <version>1.0</version> <scope>system</scope> <systemPath>${basedir}/src/main/webapp/WEB-INF/lib/paypal_base.jar</systemPath> </dependency> 上面的groupId和artifactId这些都可随便填写就好.

2016-03-12 · 1 min · 59 words · -

BigDecimal

BigDecimal package com.wiloon.javax; import java.math.BigDecimal; public class BigDecimalTest { public static void main(String[] args) { BigDecimal a = new BigDecimal(1234567890123456.1234); System.out.println("a values is:" + a); BigDecimal b = new BigDecimal(123456789012345.1234); System.out.println("b values is:" + b); BigDecimal c = new BigDecimal(12345678901234.1234); System.out.println("c values is:" + c); BigDecimal d = new BigDecimal(1234567890123.1234); System.out.println("d values is:" + d); BigDecimal e = new BigDecimal(123456789012.1234); System.out.println("e values is:" + e); // 创建一个BigDecimal对象 BigDecimal bigDecimal = new BigDecimal("1234567890123456.1234"); // 输出 System.out.println("处理的浮点数为: " + bigDecimal); System.out.println(bigDecimal.add(new BigDecimal(1))); System.out.println(bigDecimal.add(new BigDecimal(0.0001))); } } a values is:1234567890123456 b values is:123456789012345.125 c values is:12345678901234.123046875 d values is:1234567890123.123291015625 e values is:123456789012.1233978271484375 处理的浮点数为: 1234567890123456.1234 1234567890123457.1234 1234567890123456.123500000000000000004792173602385929598312941379845142364501953125 Java 在 java.math 包中提供的 API 类 BigDecimal, 用来对超过 16 位有效位的数进行精确的运算。双精度浮点型变量 double 可以处理 16 位有效数。在实际应用中,需要对更大或者更小的数进行运算和处理。 float和double只能用来做科学计算或者是工程计算,在商业计算中要用java.math.BigDecimal。BigDecimal所创建的是对象,我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。构造器是类的特殊方法,专门用来创建对象,特别是带有参数的对象。 ...

2016-02-29 · 2 min · 258 words · -

LMAX Disruptor

LMAX Disruptor LMAX Disruptor 一个高性能、低延迟且简单的框架 原文地址: LMAX Disruptor – High Performance, Low Latency and Simple Too 翻译: 杨帆 校对: 丁一 Disruptor 是一个用于在线程间通信的高效低延时的消息组件,它像个增强的队列,并且它是让LMAX Exchange 跑的如此之快的一个关键创新。关于什么是Disruptor、为何它很重要以及它的工作原理方面的信息都呈爆炸性增长 —— 这些文章很适合开始学习Disruptor,还可跟着LMAX BLOG深入学习。这里还有一份更详细的白皮书。 虽然disruptor模式使用起来很简单,但是建立多个消费者以及它们之间的依赖关系需要的样板代码太多了。为了能快速又简单适用于99%的场景,我为Disruptor模式准备了一个简单的领域特定语言。例如,为建立一个消费者的"四边形模式": (从Trisha Gee’s excellent series explaining the disruptor pattern偷来的图片) 在这种情况下,只要生产者 (P1) 将元素放到ring buffer上,消费者C1和C2就可以并行处理这些元素。但是消费者C3必须一直等到C1和C2处理完之后,才可以处理。在现实世界中的对应的案例就像: 在处理实际的业务逻辑 (C3) 之前,需要校验数据 (C1) ,以及将数据写入磁盘 (C2) 。 用原生的Disruptor语法来创建这些消费者的话代码如下: Executor executor = Executors.newCachedThreadPool(); BatchHandler handler1 = new MyBatchHandler1(); BatchHandler handler2 = new MyBatchHandler2(); BatchHandler handler3 = new MyBatchHandler3() RingBuffer ringBuffer = new RingBuffer(ENTRY_FACTORY, RING_BUFFER_SIZE); ...

2016-02-15 · 1 min · 156 words · -

DataX

DataX http://www.open-open.com/lib/view/open1325771223625.html DataX是什么? DataX是一个在异构的数据库/文件系统之间高速交换数据的工具,实现了在任意的数据处理系统(RDBMS/Hdfs/Local filesystem) 之间的数据交换,由淘宝数据平台部门完成。 DataX用来解决什么? 目前成熟的数据导入导出工具比较多,但是一般都只能用于数据导入或者导出,并且只能支持一个或者几个特定类型的数据库。这样带来的一个问题是,如果我们拥 有很多不同类型的数据库/文件系统(MySQL/Oracle/Rac/Hive/Other…),并且经常需要在它们之间导入导出数据,那么我们可能需 要开发/维护/学习使用一批这样的工具(jdbcdump/dbloader/multithread/getmerge+sqlloader /MySQLdumper…)。而且以后每增加一种库类型,我们需要的工具数目将线性增长。(当我们需要将MySQL的数据导入oracle的时候,有没 有过想从jdbcdump和dbloader上各掰下来一半拼在一起到冲动?) 这些工具有些使用文件中转数据,有些使用管道,不同程度的为数据中转带来额外开销,效率差别很非常大。很多工具也无法满足ETL任务中常见的需求,比如日 期格式转化,特性字符的转化,编码转换。另外,有些时候,我们希望在一个很短的时间窗口内,将一份数据从一个数据库同时导出到多个不同类型的数据库。 DataX正是为了解决这些问题而生。 我们只需要针对新增的数据源开发的一套Reader/Writer插件,即可实现任意数据的互导 DataX特点? 在异构的数据库/文件系统之间高速交换数据 采用Framework + plugin架构构建,Framework处理了缓冲,流控,并发,上下文加载等高速数据交换的大部分技术问题,提供了简单的接口与插件交互,插件仅需实现对数据处理系统的访问 运行模式: stand-alone 数据传输过程在单进程内完成,全内存操作,不读写磁盘,也没有IPC 开放式的框架,开发者可以在极短的时间开发一个新插件以快速支持新的数据库/文件系统。 (具体参见《DataX插件开发指南》) DataX结构模式 (框架+插件) Job: 一道数据同步作业 Splitter: 作业切分模块,将一个大任务与分解成多个可以并发的小任务. Sub-job: 数据同步作业切分后的小任务 Reader(Loader): 数据读入模块,负责运行切分后的小任务,将数据从源头装载入DataX Storage: Reader和Writer通过Storage交换数据 Writer(Dumper): 数据写出模块,负责将数据从DataX导入至目的数据地 DataX框架内部通过双缓冲队列、线程池封装等技术, 集中处理了高速数据交换遇到的问题, 提供简单的接口与插件交互, 插件分为Reader和 Writer 两类, 基于框架提供的插件接口,可以十分便捷的开发出需要的插件。比如想要从oracle导出数据到MySQL,那么需要做的就是开发出 OracleReader和MySQLWriter插件,装配到框架上即可。并且这样的插件一般情况下在其他数据交换场合是可以通用的。更大的惊喜是我们 已经开发了如下插件: Reader插件 hdfsreader : 支持从hdfs文件系统获取数据。 MySQLreader: 支持从MySQL数据库获取数据。 sqlserverreader: 支持从sqlserver数据库获取数据。 oraclereader : 支持从oracle数据库获取数据。 streamreader: 支持从stream流获取数据 (常用于测试) httpreader : 支持从http URL获取数据。 Writer插件 hdfswriter: 支持向hdbf写入数据。 ...

2015-09-25 · 1 min · 91 words · -

java.sql.Timestamp cannot be cast to java.sql.Date

java.sql.Timestamp cannot be cast to java.sql.Date java.sql.Timestamp cannot be cast to java.sql.Date date数据库sqlstringjava java.lang.ClassCastException: java.sql.Timestamp cannot be cast to java.sql.Date 我在往数据库插入数据时用的是string型,SQL应该会转换为java.sql.Date型,但是取出值的时候不也应该是java.sql.Date型么? 但是这么会报这样的错误?还有一个问题,用你说的这种方式生成的java.sql.Date好像只有年月日, 我想要取到很详细的当前时间,包括到毫秒级别,这样应该怎样生成呢??? java.sql.Date->java.sql.Timestamp new java.sql.Timestamp(yourDate.getTime()); java.sql.Timestamp->java.sql.Date new java.sql.Date(yourTimestamp.getTime()); 界面要显示毫秒的话,在date传到前面时转化格式即可! Date b_date = new Date();(着这是util类型的)! ps.setDate(new java.sql.Date(b_date.getTime()));(这是插入数据库是的Date)! 其中 (new java.sql.Date(b_date.getTime()));是把java类型的Date转换成sql类型的Date

2015-09-22 · 1 min · 40 words · -

LinkedBlockingQueue

LinkedBlockingQueue 基于链表的阻塞队列,同 ArrayBlockingQueue 类似,其内部也维持着一个数据缓冲队列 (该队列是一个链表) ,生产者存入的数据会缓存在队列内部,生产者立即返回;只有当队列缓冲区达到最大值缓存容量时 (LinkedBlockingQueue 可以通过构造函数指定该值) ,才会阻塞生产者队列,直到消费者从队列中消费掉一份数据,生产者线程会被唤醒,反之对于消费者这端的处理也基于同样的原理。而LinkedBlockingQueue 之所以能够高效的处理并发数据,还因为其对于生产者端和消费者端 分别采用了独立的锁 来控制数据同步,这也意味着在高并发的情况下生产者和消费者可以并行地操作队列中的数据,以此来提高整个队列的并发性能。 作为开发者,我们需要注意的是,如果构造一个 LinkedBlockingQueue 对象,而没有指定其容量大小,LinkedBlockingQueue 会默认一个类似无限大小的容量 (Integer.MAX_VALUE) ,这样的话,如果生产者的速度一旦大于消费者的速度,也许还没有等到队列满阻塞产生,系统内存就有可能已被消耗殆尽了。 此队列按 FIFO (先进先出) 排序元素。队列的头部 是在队列中时间最长的元素。队列的尾部 是在队列中时间最短的元素。 新元素插入到队列的尾部,并且队列检索操作会获得位于队列头部的元素。链接队列的吞吐量通常要高于基于数组的队列, 但是在大多数并发应用程序中,其可预知的性能要低。 可选的容量范围构造方法参数作为防止队列过度扩展的一种方法。 如果未指定容量,默认容量为 Integer.MAX_VALUE ,容量范围可以在构造方法参数中指定作为防止队列过度扩展。 此对象是线程阻塞-线程安全的 不接受 null 元素 它实现了BlockingQueue接口。 实现了 Collection 和 Iterator 接口的所有可选方法。 在JDK5/6中,LinkedBlockingQueue和ArrayBlocingQueue等对象的poll(long timeout, TimeUnit unit)存在内存泄露Leak的对象AbstractQueuedSynchronizer.Node,据称JDK5会在Update12里Fix,JDK6会在Update2里Fix 下面介绍几种常用的方法: 定义一个输出方法: static void v(Object s){System.out.println(s.toString());} LinkedBlockingQueue bq=new LinkedBlockingQueue(); for(int i=0;i<100;i++) { bq.add(“i”+i);//如果空间已满,此方法会抛出异常,所以这就是put,或者offer方法的优势所在 } String s1=bq.take();//i0 String s2=bq.take();//i1 bq.offer(“ix”,5,TimeUnit.SECONDS);//在尾部插入一个元素,如果有必要 ,等待 指定的时间,使得队列变得可用。返回boolean值 表示是否插入成功。 ...

2015-09-14 · 2 min · 426 words · -

LinkedTransferQueue

LinkedTransferQueue LinkedTransferQueue是在JDK1.7时,J.U.C包新增的一种比较特殊的阻塞队列,它除了具备阻塞队列的常用功能外,还有一个比较特殊的transfer方法。 我们知道,在普通阻塞队列中,当队列为空时,消费者线程(调用take或poll方法的线程)一般会阻塞等待生产者线程往队列中存入元素。而LinkedTransferQueue的transfer方法则比较特殊: 当有消费者线程阻塞等待时,调用transfer方法的生产者线程不会将元素存入队列,而是直接将元素传递给消费者; 如果调用transfer方法的生产者线程发现没有正在等待的消费者线程,则会将元素入队,然后会阻塞等待,直到有一个消费者线程来获取该元素。 有一篇论文讨论了其算法与性能: 地址: http://www.cs.rice.edu/~wns1/papers/2006-PPoPP-SQ.pdf LinkedTransferQueue 实现了一个重要的接口 TransferQueue, 该接口含有下面几个重要方法: transfer(E e) 若当前存在一个正在等待获取的消费者线程,即立刻移交之;否则,会插入当前元素e到队列尾部,并且等待进入阻塞状态,到有消费者线程取走该元素。 tryTransfer(E e) 若当前存在一个正在等待获取的消费者线程 (使用take()或者poll()函数) ,使用该方法会即刻转移/传输对象元素e; 若不存在,则返回false,并且不进入队列。这是一个不阻塞的操作。 tryTransfer(E e, long timeout, TimeUnit unit) 若当前存在一个正在等待获取的消费者线程,会立即传输给它; 否则将插入元素e到队列尾部,并且等待被消费者线程获取消费掉, 若在指定的时间内元素e无法被消费者线程获取,则返回false,同时该元素被移除。 hasWaitingConsumer() 判断是否存在消费者线程 getWaitingConsumerCount() 获取所有等待获取元素的消费线程数量 其实transfer方法在SynchronousQueue的实现中就已存在了,只是没有做为API暴露出来。SynchronousQueue有一个特性:它本身不存在容量,只能进行线程之间的 元素传送。SynchronousQueue在执行offer操作时,如果没有其他线程执行poll,则直接返回false.线程之间元素传送正是通过transfer方法完成的。 有一个使用案例,我们知道ThreadPoolExecutor调节线程的原则是: 先调整到最小线程,最小线程用完后,他会将优先将任务放入缓存队列(offer(task)),等缓冲队列用完了,才会向最大线程数调节。这似乎与我们所理解的线程池模型有点不同。我们一般采用增加到最大线程后,才会放入缓冲队列中,以达到最大性能。ThreadPoolExecutor代码片段: public void execute(Runnable command) { if (command == null) throw new NullPointerException(); if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) { if (runState == RUNNING && workQueue.offer(command)) { if (runState != RUNNING || poolSize == 0) ensureQueuedTaskHandled(command); } else if (!addIfUnderMaximumPoolSize(command)) ...

2015-09-14 · 1 min · 160 words · -

SynchronousQueue

SynchronousQueue http://wsmajunfeng.iteye.com/blog/1629352/ SynchronousQueue 是这样一种阻塞队列,其中每个 put 必须等待一个 take, 反之亦然。同步队列没有任何内部容量,甚至连一个队列的容量都没有。 不能在同步队列上进行 peek,因为仅在试图要取得元素时,该元素才存在; 除非另一个线程试图移除某个元素, 否则也不能 (使用任何方法) 添加元素; 也不能迭代队列, 因为其中没有元素可用于迭代。队列的头是尝试添加到队列中的首个已排队线程元素; 如果没有已排队线程,则不添加元素并且头为 null。 对于其他 Collection 方法 (例如 contains) ,SynchronousQueue 作为一个空集合。此队列不允许 null 元素。 它非常适合于传递性设计,在这种设计中,在一个线程中运行的对象要将某些信息、 事件或任务传递给在另一个线程中运行的对象,它就必须与该对象同步。 对于正在等待的生产者和使用者线程而言,此类支持可选的公平排序策略。默认情况下不保证这种排序。 但是,使用公平设置为 true 所构造的队列可保证线程以 FIFO 的顺序进行访问。 公平通常会降低吞吐量,但是可以减小可变性并避免得不到服务。 注意1: 它一种阻塞队列,其中每个 put 必须等待一个 take,反之亦然。同步队列没有任何内部容量,甚至连一个队列的容量都没有。 注意2: 它是线程安全的,是阻塞的。 注意3:不允许使用 null 元素。 注意4: 公平排序策略是指调用 put 的线程之间, 或 take 的线程之间。公平排序策略可以查考 ArrayBlockingQueue 中的公平策略。 注意5: SynchronousQueue 的以下方法: iterator() 永远返回空,因为里面没东西。 peek() 永远返回null。 put() 往queue放进去一个element以后就一直wait直到有其他thread进来把这个element取走。 offer() 往queue里放一个element后立即返回,如果碰巧这个element被另一个thread取走了,offer方法返回true,认为offer成功;否则返回false。 offer(2000, TimeUnit.SECONDS) 往queue里放一个element但是等待指定的时间后才返回,返回的逻辑和offer()方法一样。 take() 取出并且remove掉queue里的element (认为是在queue里的。。。) ,取不到东西他会一直等。 ...

2015-09-14 · 1 min · 110 words · -

java metrics

java metrics Metrics 类型 Counters Counter 就是计数器, Counter 只是用 Gauge 封装了 AtomicLong Gauges 最简单的度量指标,只有一个简单的返回值,例如,我们想衡量一个待处理队列中任务的个数 Meters Meter度量一系列事件发生的速率 (rate),例如 TPS, Meters 会统计最近 1分钟,5分钟,15分钟,还有全部时间的速率。 Histograms Histogram 统计数据的分布情况。比如最小值,最大值,中间值,还有中位数,75百分位, 90百分位, 95百分位, 98百分位, 99百分位, 和 99.9百分位的值 (percentiles)。 Timers Timer其实是 Histogram 和 Meter 的结合, histogram 某部分代码/调用的耗时, meter 统计 TPS 其他 除此之外,Metrics还提供了 HealthCheck 用来检测某个某个系统是否健康,例如数据库连接是否正常。还有Metrics Annotation,可以很方便地实现统计某个方法,某个值的数据。感兴趣的可以点进链接看看。 https://mvnrepository.com/artifact/io.dropwizard.metrics/metrics-core gradle dependency compile group: 'io.dropwizard.metrics', name: 'metrics-core', version: '3.1.2' private static final MetricRegistry metrics = new MetricRegistry(); private static ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build(); private static final Meter meter = metrics.meter(name(DruidTest.class, "request")); meter.mark(); reporter.report(); //Timer public class TimerTest { public static Random random = new Random(); public static void main(String[] args) throws InterruptedException { MetricRegistry registry = new MetricRegistry(); ConsoleReporter reporter = ConsoleReporter.forRegistry(registry).build(); reporter.start(1, TimeUnit.SECONDS); Timer timer = registry.timer(MetricRegistry.name(TimerTest.class,"get-latency")); Timer.Context ctx; while(true){ ctx = timer.time(); Thread.sleep(random.nextInt(1000)); ctx.stop(); } } } http://www.cnblogs.com/nexiyi/p/metrics_sample_1.html http://blog.csdn.net/hengyunabc/article/details/44072285 http://wuchong.me/blog/2015/08/01/getting-started-with-metrics/ ...

2015-09-08 · 1 min · 172 words · -

Java NIO 框架 Netty, Mina, Grizzly

Java NIO 框架 Netty, Mina, Grizzly Netty Netty是一款异步的事件驱动的网络应用框架和工具,用于快速开发可维护的高性能、高扩展性协议服务器和客户端。也就是说,Netty是一个NIO客户端/服务器框架,支持快速、简单地开发网络应用,如协议服务器和客户端。它极大简化了网络编程,如TCP和UDP socket 服务器。 Mina Mina(Multipurpose Infrastructure for Network Applications) 是 Apache 组织一个较新的项目,它为开发高性能和高可用性的网络应用程序提供了非常便利的框架。当前发行的 Mina 版本2.04支持基于 Java NIO 技术的 TCP/UDP 应用程序开发、串口通讯程序,Mina 所支持的功能也在进一步的扩展中。目前,正在使用 Mina的应用包括: Apache Directory Project、AsyncWeb、AMQP (Advanced Message Queuing Protocol) 、RED5 Server (Macromedia Flash Media RTMP) 、ObjectRADIUS、 Openfire等等。 Grizzly: Grizzly是一种应用程序框架,专门解决编写成千上万用户访问服务器时候产生的各种问题。使用JAVA NIO作为基础,并隐藏其编程的复杂性。容易使用的高性能的API。带来非阻塞socketd到协议处理层。利用高性能的缓冲和缓冲管理使用高性能的线程池。 OK,我们现在可以看看三者的简单对比了。 首先,从设计的理念上来看,Mina的设计理念是最为优雅的。当然,由于Netty的主导作者与Mina的主导作者是同一人,出自同一人之手的Netty在设计理念上与Mina基本上是一致的。而Grizzly在设计理念上就较差了点,几乎是Java NIO的简单封装。 其次,从项目的出身来看,Mina出身于开源界的大牛Apache组织,Netty出身于商业开源大亨Jboss,而Grizzly则出身于土鳖Sun公司。从其出身可以看到其应用的广泛程序,到目前为止,我见到业界还是使用Mina多一些,而Netty也在慢慢的应用起来,而Grizzly则似乎只有Sun自已的项目使用了,如果还有其他的公司或开源项目在使用,那就算我孤陋寡闻。 最后,从入门的文档来说,由于Mina见世时间相对较长,官方以及民间的文档与入门示例都相当的多。Netty的官方文档也做得很好,而民间文档就要相对于Mina少一些了。至于Grizzly,不管是官方还是民间,都很少见到其文档。 http://www.blogjava.net/javagrass/archive/2011/07/05/353680.html

2015-08-31 · 1 min · 52 words · -

ConcurrentHashMap

ConcurrentHashMap ConcurrentHashMap 是一个线程安全的Hash Table,它的主要功能是提供了一组和HashTable功能相同但是线程安全的方法。ConcurrentHashMap可以做到读取数据不加锁,并 且其内部的结构可以让其在进行写操作的时候能够将锁的粒度保持地尽量地小,不用对整个ConcurrentHashMap加锁。 jdk1.7 由 Segment 数组、HashEntry 组成,和 HashMap 一样,仍然是数组加链表。 它的核心成员变量: /** * Segment 数组,存放数据时首先需要定位到具体的 Segment 中。 */ final Segment<K,V>[] segments; transient Set<K> keySet; transient Set<Map.Entry<K,V>> entrySet; Segment 是 ConcurrentHashMap 的一个内部类,主要的组成如下: static final class Segment<K,V> extends ReentrantLock implements Serializable { private static final long serialVersionUID = 2249069246763182397L; // 和 HashMap 中的 HashEntry 作用一样,真正存放数据的桶 transient volatile HashEntry<K,V>[] table; transient int count; transient int modCount; transient int threshold; final float loadFactor; } 和 HashMap 非常类似,唯一的区别就是其中的核心数据如 value ,以及链表都是 volatile 修饰的,保证了获取时的可见性。 ...

2015-08-12 · 8 min · 1510 words · -

java ByteBuffer

java ByteBuffer ByteBuffer 是 NIO 里用得最多的 Buffer, 它包含两个实现方式: HeapByteBuffer 是基于Java堆的实现, 而 DirectByteBuffer 则使用了 unsafe 的 API 进行了堆外的实现。这里只说 HeapByteBuffer。 Buffer 类 定义了一个可以线性存放primitive type数据的容器接口。Buffer主要包含了与类型 (byte, char…) 无关的功能。 值得注意的是Buffer及其子类都不是线程安全的。 每个Buffer都有以下的属性: capacity 这个Buffer最多能放多少数据。capacity一般在buffer被创建的时候指定。 limit 在Buffer上进行的读写操作都不能越过这个下标。当写数据到buffer中时,limit一般和capacity相等,当读数据时, limit代表buffer中有效数据的长度。 position 读/写操作的当前下标。当使用buffer的相对位置进行读/写操作时,读/写会从这个下标进行,并在操作完成后, buffer会更新下标的值。 mark 一个临时存放的位置下标。调用mark()会将mark设为当前的position的值,以后调用reset()会将position属性设 置为mark的值。mark的值总是小于等于position的值,如果将position的值设的比mark小,当前的mark值会被抛弃掉。 这些属性总是满足以下条件: 0 <= mark <= position <= limit <= capacity limit和position的值除了通过limit()和position()函数来设置,也可以通过下面这些函数来改变: Buffer clear() 把position设为0,把limit设为capacity,一般在把数据写入Buffer前调用。 Buffer flip() 把limit设为当前position,把position设为0,一般在从Buffer读出数据前调用。 Buffer rewind() 把position设为0,limit不变,一般在把数据重写入Buffer前调用。 Buffer 对象有可能是只读的, 这时, 任何对该对象的写操作都会触发一个 ReadOnlyBufferException isReadOnly()方法可以用来判断一个Buffer是否只读。 Buffer是一个抽象的基类 派生类: ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer ...

2015-08-05 · 4 min · 754 words · -

线程

线程 进程在各自独立的空间中运行,进程之间共享数据需要用 mmap 或者进程间通信机制 (IPC) 如何在一个进程空间中执行多个线程,有些情况需要在一个进程中同时执行多个控制流程,这时候线程就派上了用场, 线程是比进程更轻量级的调度执行单位,线程的引入可以把一个进程的资源分配和执行调度分开,各个线程既可以共享进程资源(内存地址,文件IO等),又可以独立调度 (线程是CPU调度的基本单位) 。 线程共享以下进程的资源和环境 文件描述符表 (重点) 每种信号的处理方式 (SIG_IGN、SIG_DFL或者自定义的信号处理函数) 当前工作目录 用户id和组id 线程有自己的私有数据 线程id 上下文信息, 包括各种寄存器的值, 程序计数器, 栈指针 栈空间 (临时变量存储在栈空间中) (重点) errno变量 信号屏蔽字 调度优先级 Linux上线程位于libpthread共享库中,因此在编译时要加上-lpthread选项 (-l :指明所链接的库) 进程与线程的联系与区别 线程是在进程内部运行的执行分支 线程是为了资源共享 (共享地址空间) ,进程是为了资源独占 (私有地址空间) Linux下没有真正的线程,它是利用轻量级进程来代替实现的 进程是分配资源 (资源管理) 的最小单元;而线程是调度资源 (程序执行) 的最小单元 线程与线程之间是独立的 实现线程主要有三种方式: 使用内核线程实现,使用用户线程实现和使用用户线程加轻量级进程混合实现。 java thread Thread Dump日志的线程信息 "resin-22129" daemon prio=10 tid=0x00007fbe5c34e000 nid=0x4cb1 waiting on condition [0x00007fbe4ff7c000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:315) at com.caucho.env.thread2.ResinThread2.park(ResinThread2.java:196) at com.caucho.env.thread2.ResinThread2.runTasks(ResinThread2.java:147) at com.caucho.env.thread2.ResinThread2.run(ResinThread2.java:118) "Timer-20" daemon prio=10 tid=0x00007fe3a4bfb800 nid=0x1a31 in Object.wait() [0x00007fe3a077a000] java.lang.Thread.State: TIMED_WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x00000006f0620ff0> (a java.util.TaskQueue) at java.util.TimerThread.mainLoop(Timer.java:552) - locked <0x00000006f0620ff0> (a java.util.TaskQueue) at java.util.TimerThread.run(Timer.java:505) 以上依次是: ...

2015-06-30 · 6 min · 1102 words · -

java transient

java transient http://www.cnblogs.com/lanxuezaipiao/p/3369962.html 我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化, java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个类的所有属性和方法都会自动序列化。 然而在实际开发过程中,我们常常会遇到这样的问题,这个类的有些属性需要序列化,而其他属性不需要被序列化,打个比方,如果一个用户有一些敏感信息 (如密码,银行卡号等) ,为了安全起见,不希望在网络操作 (主要涉及到序列化操作,本地序列化缓存也适用) 中被传输,这些信息对应的变量就可以加上transient关键字。换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。 总之,java 的transient关键字为我们提供了便利,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。 一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。 transient 关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。 被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。 第三点可能有些人很迷惑,因为发现在User类中的username字段前加上static关键字后,程序运行结果依然不变,即static类型的username也读出来为"Alexia"了,这不与第三点说的矛盾吗?实际上是这样的: 第三点确实没错 (一个静态变量不管是否被transient修饰,均不能被序列化) ,反序列化后类中static型变量username的值为当前JVM中对应static变量的值,这个值是JVM中的不是反序列化得出的, 我们知道在Java中,对象的序列化可以通过实现两种接口来实现,若实现的是Serializable接口,则所有的序列化将会自动进行,若实现的是Externalizable接口,则没有任何东西可以自动序列化,需要在writeExternal方法中进行手工指定所要序列化的变量,这与是否被transient修饰无关。因此第二个例子输出的是变量content初始化的内容,而不是null。

2015-06-28 · 1 min · 21 words · -

ReferenceQueue

ReferenceQueue 引用队列 ReferenceQueue 使用 SoftReference,WeakReference,PhantomReference 的时候,可以关联一个 ReferenceQueue。那么当垃圾回收器准备回收一个被引用包装的对象时,该引用会被加入到关联的 ReferenceQueue。程序可以通过判断引用队列中是否已经加入引用, 来了解被引用的对象是否被GC回收。 作者: leilifengxingmw 链接: https://www.jianshu.com/p/6ae4f53a4752 来源: 简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 http://www.iflym.com/index.php/java-programe/201407140001.html 在java的引用体系中,存在着强引用,软引用,虚引用,幽灵引用,这4种引用类型。在正常的使用过程中,我们定义的类型都是强引用的,这种引用类型在回收中,只有当其它对象没有对这个对象的引用时,才会被GC回收掉。简单来说,对于以下定义: Object obj = new Object(); Ref ref = new Ref(obj); 在这种情况下,如果 ref 没有被 GC,那么 obj 这个对象肯定不会 GC 的。因为 ref 引用到了 obj。如果 obj 是一个大对象呢,多个这种对象的话,应用肯定一会就挂掉了。 那么,如果我们希望在这个体系中,如果obj没有被其它对象引用,只是在这个Ref中存在引用时,就把obj对象gc掉。这时候就可以使用这里提到的Reference对象了。 我们希望当一个对象被gc掉的时候通知用户线程,进行额外的处理时,就需要使用引用队列了。ReferenceQueue即这样的一个对象,当一个obj被gc掉之后,其相应的包装类,即ref对象会被放入queue中。我们可以从queue中获取到相应的对象信息,同时进行额外的处理。比如反向操作,数据清理等。 2 使用队列进行数据监控 一个简单的例子,通过往map中放入10000个对象,每个对象大小为1M字节数组。使用引用队列监控被放入的key的回收情况。代码如下所示: Object value = new Object(); Map<Object, Object> map = new HashMap<>(); for(int i = 0;i < 10000;i++) { byte[] bytes = new byte[_1M]; WeakReference<byte[]> weakReference = new WeakReference<byte[]>(bytes, referenceQueue); map.put(weakReference, value); } System.out.println("map.size->" + map.size()); 这里使用了weakReference对象,即当值不再被引用时,相应的数据被回收。另外使用一个线程不断地从队列中获取被gc的数据,代码如下: ...

2015-06-26 · 2 min · 262 words · -