
道路多歧,善择者少走弯路;人生多惑,善辨者少入迷途。
能力说明:
精通JVM运行机制,包括类生命、内存模型、垃圾回收及JVM常见参数;能够熟练使用Runnable接口创建线程和使用ExecutorService并发执行任务、识别潜在的死锁线程问题;能够使用Synchronized关键字和atomic包控制线程的执行顺序,使用并行Fork/Join框架;能过开发使用原始版本函数式接口的代码。
暂时未有相关云产品技术能力~
阿里云技能认证
详细说明作者:毕来生 前言 个人比较看好Spring Cloud Alibaba家族。此系列以Nacos为主题,从Spring、Spring boot、Spring Cloud多个方面逐步进行演示,源码解读。目前来看官方文档还有待完善。网络上除了官网外缺少Nacos系列文章。都是零零散散的知识点。如此系列文章哪里写的有不周全,错误之处。欢迎大家指正。谢谢。 因公众号排版问题,可能会有代码显示不完整,请使用电脑版微信内置浏览器/复制链接到浏览器中。 第一篇 : 【Nacos系列第一篇】-Nacos之Spring Discovery 以及Config。 第二篇 : 【Nacos系列第二篇】-Nacos之Spring Boot Discovery。 因大家在工作中逐步以Spring boot、Spring Cloud为主进行开发。我们接下来会以这两个为核心演示详解。 Nacos架构图 工程结构 上面说了那么多,现在先来看一下我们的Spring boot Nacos config工程结构(Windows下演示) Spring Boot版本:2.1.2.RELEASE 准备工作 1、启动Nacos(Demo演示环境为Windows下) 2、访问http://127.0.0.1:8848/nacos/index.html#/configurationManagement?dataId=&group=&appName=&namespace= 进入Nacos配置管理页面 3、点击左侧配置管理->配置列表(右侧有一个加号。添加对应信息),如下图 以上就是我们要做的准备工作啦。 获取ConfigService方法 1、通过@NacosInjected注解获取 @NacosInjected ConfigService configService; 2、通过NacosFactory传入Properties获取 ConfigService configService = NacosFactory.createConfigService(properties); 3、通过NacosFactory传入ServerAddr获取 ConfigService configService = NacosFactory.createConfigService(serverAddr); 以上方式均是为反射获取,NacosFactory创建ConfigService实际上也是调用ConfigFactory.createConfigService实现的 /** * Create config * * @param properties * init param * @return config * @throws NacosException * Exception */ public static ConfigService createConfigService(Properties properties) throws NacosException { return ConfigFactory.createConfigService(properties); } 附上创建ConfigService源码 /** * Create Config * * @param ServerAddr * serverlist * @return Config * @throws NacosException * Exception */ public static ConfigService createConfigService(String serverAddr) throws NacosException { Properties properties = new Properties(); properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr); try { Class<?> driverImplClass = Class.forName("com.alibaba.nacos.client.config.NacosConfigService"); Constructor constructor = driverImplClass.getConstructor(Properties.class); ConfigService vendorImpl = (ConfigService) constructor.newInstance(properties); return vendorImpl; } catch (Throwable e) { throw new NacosException(-400, e.getMessage()); } } 代码演示 附上与普通创建的Spring boot工程不同点(以下演示为通过配置管理代码示例中相同获取方式) ConfigController(新增) package org.nacos.springboot.controller; import com.alibaba.nacos.api.NacosFactory; import com.alibaba.nacos.api.PropertyKeyConst; import com.alibaba.nacos.api.config.ConfigService; import com.alibaba.nacos.api.config.listener.Listener; import com.alibaba.nacos.api.exception.NacosException; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.concurrent.Executor; /** * @author bilaisheng * @wechat: 878799579 * @date 2019/01/15 19:34 * @description Test Nacos Config */ @Controller @RequestMapping("config") public class ConfigController { /** * @author : bilaisheng * @wechat: 878799579 * @date : 2019/01/15 19:45 * @return Map * @throws NacosException * @throws InterruptedException */ @ResponseBody @RequestMapping("/get") public Map getConfig() throws NacosException, InterruptedException { // 用以演示用,页面返回数据展示 Map map = new HashMap(); // 服务地址。本机演示故写localhost。请根据实际情况替换对应IP String serverAddr = "localhost"; String dataId = "nacos-spring"; String group = "bilaisheng"; Properties properties = new Properties(); properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr); // 创建ConfigService,此处通过Properties方式进行创建,另一种演示serviceaddr获取configService. // 原理上都是通过 ConfigFactory.createConfigService()去进行创建 ConfigService configService = NacosFactory.createConfigService(properties); // ConfigService configService = NacosFactory.createConfigService(serverAddr); String content = configService.getConfig(dataId, group, 5000); System.out.println("config : " + content); map.put("content", content); // 添加Listener,用以演示receive获取数据结果 configService.addListener(dataId, group, new Listener() { @Override public void receiveConfigInfo(String configInfo) { System.out.println("recieve : " + configInfo); } @Override public Executor getExecutor() { return null; } }); // 推送config。将原有dataid中信息替换。 boolean isPublishOk = configService.publishConfig(dataId, group, "publish config content"); System.out.println("isPublishOk : " + isPublishOk); map.put("isPublishOk", isPublishOk); Thread.sleep(3000); content = configService.getConfig(dataId, group, 5000); System.out.println("Thread sleep 3000ms : " + content); map.put("Thread sleep 3000ms : ", content); // 删除指定dataid , group 配置 boolean isRemoveOk = configService.removeConfig(dataId, group); System.out.println("remove " + dataId + "config is " + isRemoveOk); Thread.sleep(3000); content = configService.getConfig(dataId, group, 5000); System.out.println("content after 5000ms "+content); Thread.sleep(3000); return map; } } application.properties nacos.config.server-addr=127.0.0.1:8848 pom.xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.alibaba.boot</groupId> <artifactId>nacos-config-spring-boot-starter</artifactId> <version>0.2.1</version> </dependency> 上述内容就是我们在创建好Spring Boot工程结构后增加/调整内容。 演示步骤 1、启动 BilaishengNacosSpringbootConfigApplication 2、调用 http://localhost:8080/config/get,此时控制台出现 页面出现 以上就是我们Spring Boot Config的一个Demo例子 喜欢就关注我吧
作者:毕来生 前言 个人比较看好Spring Cloud Alibaba家族。此系列以Nacos为主题,从Spring、Spring boot、Spring Cloud多个方面逐步进行演示,源码解读。目前来看官方文档还有待完善。网络上除了官网外缺少Nacos系列文章。都是零零散散的知识点。如此系列文章哪里写的有不周全,错误之处。欢迎大家指正。谢谢。 因公众号排版问题,可能会有代码显示不完整,请使用电脑版微信内置浏览器/复制链接到浏览器中。 上一篇已经描述了Nacos中Spring Discovery 以及Config演示。 因大家在工作中逐步以Spring boot、Spring Cloud为主进行开发。我们接下来会以这两个为核心演示详解。 Nacos架构图 工程结构 上面说了那么多,现在先来看一下我们的Spring boot Nacos Discovery工程结构(Windows下演示) Spring Boot版本:2.1.2.RELEASE 附上与普通创建的Spring boot工程不同点 NacosDiscoveryController(新增) package org.nacos.springboot.controller; import com.alibaba.nacos.api.annotation.NacosInjected; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.naming.NamingService; import com.alibaba.nacos.api.naming.pojo.Instance; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import java.util.List; @Controller @RequestMapping("nacos") public class NacosDiscoveryController { @NacosInjected private NamingService namingService; @RequestMapping("/instance") @ResponseBody public List<Instance> getAllInstance(@RequestParam String servicename) throws NacosException { return namingService.getAllInstances(servicename); } } application.properties nacos.discovery.server-addr=127.0.0.1:8848 pom.xml <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.alibaba.boot</groupId> <artifactId>nacos-discovery-spring-boot-starter</artifactId> <version>0.2.1</version> </dependency> </dependencies> 上述内容就是我们在创建好Spring Boot工程结构后增加/调整内容。 演示步骤 1、启动好我们的Nacos 2、启动 BilaishengNacosSpringbootApplication 3、调用 curl http://localhost:8080/nacos/instance?serviceName=nacos-spring,此时返回为空 JSON 数组[]。 4、官方告诉你说执行下方命令。模拟请求(别看就这一句话。很坑) curl -X PUT 'http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=example&ip=127.0.0.1&port=8080' #### 踩坑之旅 环境:Windows7 (想着演示用,偷偷懒。结果把自己坑了。)我们来说一下有多坑。 直接cmd。提示curl 不是内部或外部命令,也不是可运行的程序 。 好吧我们下载一个。官网地址:https://curl.haxx.se/。根据系统选择不同的版本。我下载的windows64. 解压。 解压下载好的文件,拷贝curl.exe文件到C:WindowsSystem32 然后就可以在DOS窗口中任意位置,使用curl命令了。但是你以为这就结束了?告诉你,不可能!!!。 纠结了很久,不知道为什么。百度说的一大堆都是废话。没有一个有用的。但是这点困难怎么会难住我们呢? 我们一条路走不通我们就换一条路嘛。给大家几个解决方案。 1、通过jdk里面自带的jconsole模拟请求(没玩过的同学可以百度一下) 2、PostMan 3、百度了一个模拟请求工具。附下图。 上面搞定了后。我们继续向下玩耍。 我们来访问一下如下地址。http://localhost:8080/nacos/instance?servicename=nacos-spring 以上就是我们Spring Boot Discovery的一个Demo例子。参考官网Demo。 喜欢就关注我吧
作者:毕来生 前言 个人比较看好Spring Cloud Alibaba家族。此系列以Nacos为主题,从Spring、Spring boot、Spring Cloud多个方面逐步进行演示,源码解读。目前来看官方文档还有待完善。网络上除了官网外缺少Nacos系列文章。都是零零散散的知识点。如此系列文章哪里写的有不周全,错误之处。欢迎大家指正。谢谢。 因公众号排版问题,可能会有代码显示不完整,请使用电脑版微信内置浏览器/复制链接到浏览器中。 1、Nacos是什么? 来自官网提供Nacos说明 服务(Service)是 Nacos 世界的一等公民。Nacos 支持几乎所有主流类型的“服务”的发现、配置和管理: Kubernetes Service gRPC & Dubbo RPC Service Spring Cloud RESTful Service Nacos 的关键特性包括一下等等: 服务发现和服务健康监测 动态配置服务 动态 DNS 服务 服务及其元数据管理 Nacos架构图 2、准备工作 工具:IDEA2018.3 、JDK: 1.8、Maven:3.5(通用配置。后续不在提及此部分。均已此版本演示) Nacos:0.7.0(写此文章时最新版本,如后续更新。以最新版本给大家演示) 环境:Windows(演示用,后续更新完成后会有一章在linux下演示。有坑,但原理一样。不多赘述。) Nacos稳定版本:https://github.com/alibaba/nacos/releases Linux下请下载tar后解压。Windows下请下载zip。 unzip nacos-server-$version.zip 或者 tar -xvf nacos-server-$version.tar.gz 下载后启动Nacos。Nacos默认启动端口为8848,意为珠穆朗玛峰高度。如启动有端口冲突,请自行调整端口。 3、工程结构 上面说了那么多,现在先整理来看一下我们的工程结构 附上关键部分代码。 NacosConfiguration package org.nacos.spring; import com.alibaba.nacos.api.annotation.NacosProperties; import com.alibaba.nacos.spring.context.annotation.config.NacosPropertySource; import com.alibaba.nacos.spring.context.annotation.discovery.EnableNacosDiscovery; import org.springframework.beans.factory.annotation.Configurable; /** * @Author: bilaisheng * @Wechat: 878799579 * @Date: 2019/1/13 19:28 * @Todo: NacosConfiguration,用以注册以及测试Service Name : nacos-spring * @Version : JDK1.8 , IDEA2018 */ @Configurable @EnableNacosConfig(globalProperties = @NacosProperties(serverAddr = "127.0.0.1:8848")) @NacosPropertySource(dataId = "nacos-spring", autoRefreshed = true) public class NacosConfiguration { } @EnableNacosConfig 注解启用 Nacos Spring 的配置管理服务。 @NacosPropertySource 加载了 dataId 为 nacos-spring`的配置源,并开启自动更新。 对 Nacos Spring 的用户来说,在自身应用中就只是设置 “autoRefreshed” 的一个布尔值。然后在需要修改配置的时候,调用 Nacos 修改配置的接口,或使用 Nacos 的控制台去修改,配置发生变更后, Nacos 就会把最新的配置推送到该应用的所有机器上。 NacosDiscoveryController package org.nacos.spring.controller; import com.alibaba.nacos.api.annotation.NacosInjected; import com.alibaba.nacos.api.config.annotation.NacosValue; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.naming.NamingService; import com.alibaba.nacos.api.naming.pojo.Instance; import com.alibaba.nacos.spring.context.annotation.discovery.EnableNacosDiscovery; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import java.util.Date; import java.util.List; import static org.springframework.web.bind.annotation.RequestMethod.GET; /** * @Author: bilaisheng * @Wechat: 878799579 * @Date: 2019/1/13 19:29 * @Todo: NacosDisCoveryTest * @Version : JDK1.8 , IDEA2018 */ @Controller @RequestMapping("nacos") public class NacosDiscoveryController { @NacosInjected private NamingService namingService; @NacosValue(value = "${useLocalCache:false}", autoRefreshed = true) private boolean useLocalCache; @RequestMapping("/{str}") public String helloNacos(@PathVariable String str){ return new Date() + "Hello Nacos " + str; } @RequestMapping("/instance") @ResponseBody public List<Instance> getInstance(@PathVariable String serviceName) throws NacosException { return namingService.getAllInstances(serviceName); } @RequestMapping(value = "/get", method = GET) @ResponseBody public boolean get() { return useLocalCache; } } 此文件为普通Spring映射控制器,话说Nacos Spring还是小马哥@mercyblitz亲自操刀。大家可以不用怀疑质量啦。相信很多同学都快被小马哥逼的要劝退了。 着重说明一下,这个也是Nacos中常用的方法之一。 @RequestMapping("/instance") @ResponseBody public List<Instance> getInstance(@PathVariable String serviceName) throws NacosException { return namingService.getAllInstances(serviceName); } 获取全部实例 List<Instance> getAllInstances(String serviceName) throws NacosException; List<Instance> getAllInstances(String serviceName, List<String> clusters) throws NacosException; 请求参数 名称 类型 描述 serviceName 字符串 服务名 clusters List 集群列表 返回参数 List 实例列表。 获取配置 描述 用于服务启动的时候从 Nacos 获取配置。 public String getConfig(String dataId, String group, long timeoutMs) throws NacosException 请求参数 参数名 参数类型 描述 dataId string 配置 ID,采用类似 package.class(如com.taobao.tc.refund.log.level)的命名规则保证全局唯一性,class 部分建议是配置的业务含义。全部字符小写。只允许英文字符和 4 种特殊字符("."、":"、"-"、"_"),不超过 256 字节。 group string 配置分组,建议填写产品名:模块名(Nacos:Test)保证唯一性,只允许英文字符和4种特殊字符("."、":"、"-"、"_"),不超过128字节。 timeout long 读取配置超时时间,单位 ms,推荐值 3000。 返回值 参数类型 描述 string 配置值 请求示例 try { String serverAddr = "{serverAddr}"; String dataId = "{dataId}"; String group = "{group}"; Properties properties = new Properties(); properties.put("serverAddr", serverAddr); ConfigService configService = NacosFactory.createConfigService(properties); String content = configService.getConfig(dataId, group, 5000); System.out.println(content); } catch (NacosException e) { // TODO Auto-generated catch block e.printStackTrace(); } 上述两个文件中关于Nacos使用,请参考官网NacosSDK。里面详细标注了每个方法以及对应参数以及测试案例。 父pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.bilaisheng.nacos</groupId> <artifactId>nacos-spring-examples</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <modules> <module>nacos-spring-discvoery</module> </modules> <name>nacos-spring-examples</name> <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <spring.framework.version>5.1.3.RELEASE</spring.framework.version> <servlet-api.version>4.0.1</servlet-api.version> <nacos-spring-context.version>0.2.2-RC1</nacos-spring-context.version> </properties> <dependencyManagement> <dependencies> <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlet-api.version}</version> <scope>provided</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-core --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.framework.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.framework.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.framework.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba.nacos/nacos-spring-context --> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-spring-context</artifactId> <version>${nacos-spring-context.version}</version> </dependency> </dependencies> </dependencyManagement> </project> 本工程pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>nacos-spring-examples</artifactId> <groupId>org.bilaisheng.nacos</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>nacos-spring-discvoery</artifactId> <dependencies> <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba.nacos/nacos-spring-context --> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-spring-context</artifactId> </dependency> </dependencies> </project> 页面请求 页面请求同普通Spring相同,启动后根据http://ip:端口/controller/xxx。 喜欢就关注我吧
作者 : 毕来生 锁状态转换 Lock分类 Jdk1.5以后帮助我们提供了线程同步机制,通过显示定义同步锁来实现对象之间的同步。还是Doug Lea这个家伙写的。相信读过源码的人在很多地方都可以看到这个家伙。 Lock可以显示的进行加锁,解锁。但是每次只能有一个线程对Lock对象加锁 Lock实现结构如下图所示: 按照使用的常用度,分别标注了(1),(2),(3)。接下来我们就主要学习一下ReentrantLock的使用 可重入锁 ReentrantLock实现的前提就是AbstractQueuedSynchronizer,简称AQS.。核心方法内部实现均在AQS中,后续我们在详细解读AQS相关知识点以及使用场景。我们先来看一段伪代码用以表述可重入锁的使用情况。接下来我们来详细分析获取锁以及释放锁内部实现到底做了什么事情。 package org.bilaisheng.juc; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * @Author: bilaisheng * @Wechat: 878799579 * @Date: 2019/1/3 22:55 * @Todo: 伪代码仅演示使用 * @Version : JDK11 , IDEA2018 */ public class ReentrantLockTest { public static void main(String[] args) { Lock lock = new ReentrantLock(); // 获取锁 lock.lock(); // access the resource protected by this lock // do something // 释放锁 lock.unlock(); } } Sync对象剖析 /** Synchronizer providing all implementation mechanics */ private final Sync sync; /** * Base of synchronization control for this lock. Subclassed * into fair and nonfair versions below. Uses AQS state to * represent the number of holds on the lock. */ abstract static class Sync extends AbstractQueuedSynchronizer { // xxxx } 他会根据传入构造方法的布尔类型参数实例化出Sync的实现类FairSync和NoFairSync。 FairSync: 公平的Sync NoFairSync : 不公平的Sync public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); } ReentrantLock.lock()实现原理 我们用的比较多的ReentrantLock是非公平锁,我们来用一张图来分析一下看看它是如何实现的。 上图就做了两件事情: 1、设置AbstractQueuedSynchronizer的state为1 2、设置AbstractOwnableSynchronizer的thread为当前线程 线程A正在执行中,status = 1。 线程B尝试利用CAS去判断state是不是0,是0就设置为1,当然这一步操作肯定是失败的,因为线程A已经将state设置成了1,所以此时肯定是失败的。 失败了之后进入FIFO等待队列。等待重新尝试 /** * Performs non-fair tryLock. tryAcquire is implemented in * subclasses, but both need nonfair try for trylock method. */ @ReservedStackAccess final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; } 因为在AbstractQueuedSynchronizer中state是用volatile关键字声明的,故可以在线程间可见 /** * The synchronization state. */ private volatile int state; 再次判断一下能否持有锁(可能线程A同步代码执行得比较快,已经释放了锁),不可以就返回false。 根据上方代码可以看出同一个锁最多能重入Integer.MAX_VALUE次,也就是2147483647。 ReentrantLock.unLock()实现原理 此处较为简单。附上调用关系链路 // 步骤一 public void unlock() { sync.release(1); } // 步骤二 : AbstractQueuedSynchronizer public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false; } //步骤二 : ReentrantLock @ReservedStackAccess protected final boolean tryRelease(int releases) { int c = getState() - releases; if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; if (c == 0) { free = true; setExclusiveOwnerThread(null); } setState(c); return free; } 当一条线程对同一个ReentrantLock全部解锁之后,AQS的state就是0了,AbstractOwnableSynchronizer的exclusiveOwnerThread将被设置为null,这样就表示没有线程占有锁,方法返回true。 喜欢就关注我吧
作者 : 毕来生 前言 在 java.util.concurrent 包中提供了多种并发容器类来改进同步容器 的性能。今天我们来聊一聊CountDownLatch 的使用场景。看看它到底是怎么玩耍的。 CountDownLatch 是干什么的? CountDownLatch 一个同步辅助类,在完成一组正在其他线程中执行的操作 之前,它允许一个或多个线程一直等待。 CountDownLatch原理 CountDownLatch是通过一个计数器来实现的,计数器的初始化值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就相应得减1。当计数器到达0时,表示所有的线程都已完成任务,然后在闭锁上等待的线程就可以恢复执行任务。 使用场景 在某些业务情况下,要求我们等某个条件或者任务完成后才可以继续处理后续任务。同时在线程完成时也会触发一定事件。方便业务继续向下执行。这个时候我们的CountDownLatch就隆重登场啦。常用核心方法为 /** * 递减计数器的计数,如果计数达到0,则释放所有等待的线程。 * 如果当前计数大于0,则将计数减少。 * 如果新的计数为0,会重启所有等待线程 * 如果当前计数等于0,则不做任何操作 **/ public void countDown() { sync.releaseShared(1); } /** * 1、当前线程在倒数至0之前会一直等待 * 2、除非线程被中断或超出了指定的时间。 * 3、如果当前计数为0,立刻返回为true * 4、如果当前计数等于0,则不做任何操作 * 5、如果当前线程在进入此方法时已经设置了该线程的中断状态, * 或者在等待时被中断,则抛出InterruptedException **/ public boolean await(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout)); } 实战演练 package org.bilaisheng.juc; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * @Author: bilaisheng * @Wechat: 878799579 * @Date: 2019/1/2 23:30 * @Todo: CountDownLatch demo。 * @Version : JDK11 , IDEA2018 */ public class CountDownLatchTest { // 举个例子:有十个毒贩在和警察激战 public static void main(String[] args) throws InterruptedException { // 开始计数器 final CountDownLatch start = new CountDownLatch(1); // 结束计数器 final CountDownLatch end = new CountDownLatch(10); final ExecutorService executorService = Executors.newFixedThreadPool(10); for (int i = 1; i <= 10; i++) { // 这个变量纯粹为了掩饰到底哪个倒霉先被干掉。 final String criminal = "第"+i+"个毒贩"; Runnable task = new Runnable() { @Override public void run() { try { // 如果当前已经没有可以毒贩,立刻返回 start.await(); Thread.sleep(500); System.out.println(criminal + "被干掉了!"); } catch (InterruptedException e) { e.printStackTrace(); } finally { // 干掉一个。毒贩活着的数量就减1 end.countDown(); } } }; executorService.submit(task); } // 抓捕开始 start.countDown(); // 全都被干掉了(计数器为0) end.await(); // 任务完成:收工回家 executorService.shutdown(); } } 闭锁可以延迟线程的进度直到其到达终止状态,闭锁可以用来确保某些活动直到其他活动都完成才继续执行: 确保某个计算在其需要的所有资源都被初始化之后才继续执行; 确保某个服务在其依赖的所有其他服务都已经启动之后才启动; 等待直到某个操作所有参与者都准备就绪再继续执行。 喜欢就关注我吧
版权声明:本文为博主原创文章,未经博主允许不得转载。如需授权请联系微信:878799579 https://blog.csdn.net/qq_878799579/article/details/85636250 作者 : 毕来生 微信: 878799579 1、CAS是什么? CAS是英文单词(Compare-And-Swap)的缩写,中文意思是:比较并替换。CAS需要有3个操作数:内存地址V,旧的预期值A,即将要更新的目标值B。 CAS指令执行时,当且仅当内存地址V的值与预期值A相等时,将内存地址V的值修改为B,否则就什么都不做。整个比较并替换的操作是一个原子操作。 Cas乐观锁算法演示 CAS优缺点 优点: 解决了部分情况下原子操作的问题 并发量不是很高时cas机制会提高效率。 缺点: 同一时间只能保证一个共享变量的原子操作(针对多个共享变量操作。循环CAS无法保证操作原子性,需要考虑通过加锁来保证原子性) 循环时间比较长,且开销时间比较大 : 如果尝试CAS失败,则会一直进行尝试。如果一直不成功。会对CPU带来较大负担 经典ABA问题 如果内存地址V初次读取的值是A,并且在准备赋值的时候检查到它的值仍然为A,那我们就能说它的值没有被其他线程改变过了吗? 如果在这段期间它的值曾经被改成了B,后来又被改回为A,那CAS操作就会误认为它从来没有被改变过。这个漏洞称为CAS操作的“ABA”问题。Java并发包为了解决这个问题,提供了一个带有标记的原子引用类“AtomicStampedReference”,它可以通过控制变量值的版本来保证CAS的正确性。因此,在使用CAS前要考虑清楚“ABA”问题是否会影响程序并发的正确性,如果需要解决ABA问题,改用传统的互斥同步可能会比原子类更高效。 如何解决经典ABA问题以及源码分析 通过JDK中自带的AtomicStampedReference类可以解决ABA问题。附上核心解决方法 /** * Atomically sets the value of both the reference and stamp * to the given update values if the * current reference is {@code ==} to the expected reference * and the current stamp is equal to the expected stamp. * * @param expectedReference the expected value of the reference(期望值) * @param newReference the new value for the reference(写入新值) * @param expectedStamp the expected value of the stamp(期望的状态值) * @param newStamp the new value for the stamp(新的状态值) * @return {@code true} if successful */ public boolean compareAndSet(V expectedReference, V newReference, int expectedStamp, int newStamp) { Pair<V> current = pair; return expectedReference == current.reference && expectedStamp == current.stamp && ((newReference == current.reference && newStamp == current.stamp) || casPair(current, Pair.of(newReference, newStamp))); } private boolean casPair(Pair<V> cmp, Pair<V> val) { return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val); } 因为casPair核心方法时通过native关键字修饰。故不能直接查看对应class源码。 public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5) 不能查看源码就能难住我们了?不存在的。 我们下载好openjdk源码后,将其导入到idea里该project的lib中,全局搜索。直接附上对应源码供大家参考 UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h)) UnsafeWrapper("Unsafe_CompareAndSwapObject"); oop x = JNIHandles::resolve(x_h); // 新值 oop e = JNIHandles::resolve(e_h); // 预期值 oop p = JNIHandles::resolve(obj); HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset);// 在内存中的具体位置 oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e, true);// 调用了另一个方法 jboolean success = (res == e); // 如果返回的res等于e,则判定满足compare条件(说明res应该为内存中的当前值),但实际上会有ABA的问题 if (success) // success为true时,说明此时已经交换成功(调用的是最底层的cmpxchg指令) update_barrier_set((void*)addr, x); // 每次Reference类型数据写操作时,都会产生一个Write Barrier暂时中断操作,配合垃圾收集器 return success; UNSAFE_END
版权声明:本文为博主原创文章,未经博主允许不得转载。如需授权请联系微信:878799579 https://blog.csdn.net/qq_878799579/article/details/85636105 作者:毕来生 微信:878799579 1、什么是原子变量? 原子变量保证了该变量的所有操作都是原子的,不会因为多线程的同时访问而导致脏数据的读取问题。 2、通过synchronized保证原子操作 获取锁对象 获取失败/获取不到 ->阻塞队列等待 释放锁对象 3、Atomic之AtomicInteger源码分析 java.util.concurrent.atomic包下帮助我们提供了很多原子性的支持,请参考下图 AtomicInteger和AtomicIntegerArray:基于Integer类型 AtomicBoolean:基于Boolean类型 AtomicLong和AtomicLongArray:基于Long类型 AtomicReference和AtomicReferenceArray:基于引用类型 构造方法如下 private volatile int value; /** * Creates a new AtomicInteger with the given initial value. * * @param initialValue the initial value */ public AtomicInteger(int initialValue) { value = initialValue; } /** * Creates a new AtomicInteger with initial value {@code 0}. */ public AtomicInteger() { } 如果通过构造方法设置原子变量。如不设置初始值则会默认初始化为0。 以下为方法为AtomicInteger基于原子操作常用方法 //获取当前原子变量中的值并为其设置新值 public final int getAndSet(int newValue) //比较当前的value是否等于expect,如果是设置为update并返回true,否则返回false public final boolean compareAndSet(int expect, int update) //获取当前的value值并自增一 public final int getAndIncrement() //获取当前的value值并自减一 public final int getAndDecrement() //获取当前的value值并为value加上delta public final int getAndAdd(int delta) 4、实战演练 在多线程下。我希望对num = 0;进行自增,10个线程,每个线程对变量自增10000次。结果应该是100000才对。 首先我们先来一个错误示范: package org.bilaisheng.juc; /** * @Author: bilaisheng * @Wechat: 878799579 * @Date: 2019/1/1 21:58 * @Todo: AtomicInteger 原子性错误示范。仅演示使用 * @Version : JDK11 , IDEA2018 */ public class AtomicIntegerErrorTest { // 举例10条线程并发,实际条数请参考自己场景 private static final int THREAD_COUNT = 10; private static int num = 0; public static void main(String[] args) { Thread[] threads = new Thread[THREAD_COUNT]; for (int i = 0; i < THREAD_COUNT; i++) { threads[i] = new Thread(new Runnable() { @Override public void run() { // 此处设置10000.太小看不到效果。请酌情设置 for (int j = 1; j <=10000 ; j++) { // 如想要看到结果请放开下行注释 //System.out.println(Thread.currentThread().getName() +" num = "+num); num++ ; } } }); threads[i].start(); } System.out.println(Thread.currentThread().getName()); System.out.println(Thread.activeCount()); while (Thread.activeCount()>2){ Thread.yield(); } System.out.println(num); } } 运行结果举例两张如下图所示。每次运行结果都不相同 接下来我们的AtomicInteger就该登场了 package org.bilaisheng.juc; import java.util.concurrent.atomic.AtomicInteger; /** * @Author: bilaisheng * @Wechat: 878799579 * @Date: 2019/1/1 23:02 * @Todo: * @Version : JDK11 , IDEA2018 */ public class AtomicIntegerTest { private static final int THREADS_CONUT = 10; public static AtomicInteger num = new AtomicInteger(0); public static void main(String[] args) { Thread[] threads = new Thread[THREADS_CONUT]; for (int i = 0; i < threads.length; i++) { threads[i] = new Thread(new Runnable() { @Override public void run() { // 此处设置10000.太小看不到效果。请酌情设置 for (int j = 1; j <=10000 ; j++) { // 如想要看到结果请放开下行注释 //System.out.println(Thread.currentThread().getName() +" num = "+num); num.incrementAndGet(); } } }); threads[i].start(); } while (Thread.activeCount() > 2) { Thread.yield(); } System.out.println(num); } } 结果是不管怎么运行结果都和预期下相同。运行结果如下图: 5、 Volatile可以保证变量原子性吗? 我们先来看一下下面两行代码 private volatile long num = 4642761357212574643L; private volatile double amt= 4642761357212574643.23165421354; 如上代码并不能保证num以及amt两个变量就是原子性的,在32位处理器中 哪怕是通过volatile关键字进行修饰也无法保证变量原子性。因为在32位系统下。如果出现了多线程同时操作某个变量。这个变量正在被线程a进行修改。此时线程b访问此变量。可能只获取到该变量的前32位,故可能会导致原子性失效。导致不可预知的情况以及错误。如果本地和生产均为64位处理器。请忽略以上废话。
版权声明:本文为博主原创文章,未经博主允许不得转载。如需授权请联系微信:878799579 https://blog.csdn.net/qq_878799579/article/details/85635932 作者:毕来生 微信:878799579 什么是JUC? JUC全称 java.util.concurrent 是在并发编程中很常用的实用工具类 2.Volatile关键字 1、如果一个变量被volatile关键字修饰,那么这个变量对所有线程都是可见的。 2、如果某条线程修改了被Volatile修饰的这个变量值,修改后的值对于其他线程来时是立即可见的。 3、并不是经过Volatile修饰过的变量在多线程下就是安全的 4、多线程间可以使用SynchronousQueue或者Exchanger进行数据之间传递 3.内存可见性 内存可见性(Memory Visibility)是指当某个线程正在使用对象状态 而另一个线程在同时修改该状态,需要确保当一个线程修改了对象 状态后,其他线程能够看到发生的状态变化。 可见性错误是指当读操作与写操作在不同的线程中执行时,我们无法确保执行读操作的线程能适时地看到其他线程写入的值,有时甚至是根本不可能的事情。 原理同CAS原理相同,不懂的同学可以自行百度,附上一张CAS演示图供大家参考 4.实战举例 通过线程来修改变量count的值,使用Volatile关键字修饰和不使用Volatile修饰count变量结果对比。 首先我们来看一下通过内部类实现Runnable,变量使用Volatile关键字修饰演示以及结果 package org.bilaisheng.juc; /** * @Author: bilaisheng * @Wechat: 878799579 * @Date: 2019/1/1 16:29 * @Todo: 通过内部类实现Runnable,变量使用Volatile关键字修饰演示 * @Version : JDK11 , IDEA2018 */ public class NoVolatileTest{ public static void main(String[] args) { NoVolatileThread noVolatileThread = new NoVolatileThread(); new Thread(noVolatileThread).start(); while (true){ if(noVolatileThread.isFlag()){ System.out.println("flag 此时为true !"); break; } } } } class NoVolatileThread implements Runnable{ private boolean flag = false; @Override public void run() { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } flag = true; System.out.println(Thread.currentThread().getName() + " flag = " + flag); } public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } } 运行结果如下图所示: 接下来我们来看一下通过内部类实现Runnable,变量不使用Volatile关键字修饰演示以及结果 package org.bilaisheng.juc; /** * @Author: bilaisheng * @Wechat: 878799579 * @Date: 2019/1/1 16:53 * @Todo: 通过内部类实现Runnable,变量使用Volatile关键字修饰演示 * @Version : JDK11 , IDEA2018 */ public class VolatileTest{ public static void main(String[] args) { VolatileThread volatileThread = new VolatileThread(); new Thread(volatileThread).start(); while (true){ // if的判断volatile保证当时确实正确,然后线程a可能处于休眠状态, // 线程b也判断不存在,b线程就new了一个。 // 然后a线程wake up,据需执行new volatile获取最新值。 if(volatileThread.isFlag()){ System.out.println("flag 此时为true !"); break; } } } } class VolatileThread implements Runnable{ private volatile boolean flag = false; @Override public void run() { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } flag = true; System.out.println(Thread.currentThread().getName() + " flag = " + flag); } public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } } 运行结果如下图所示: 通过对比我们发现在通过Volatile修饰和不通过Volatile修饰的变量,输出结果竟然会有些偏差。到底是为什么呢? 我们逐步拆解上面代码执行步骤: 1、针对于不使用Volatile关键字修饰变量: 步骤一:默认flag = false; 步骤二main线程的缓存区域没有刷新 flag的值。所以flag 还是false。故没有输出<flag 此时为true !> 步骤三:子线程输出 Thread-0 flag = true 2、针对于使用Volatile关键字修饰变量: 步骤一:默认flag = false; 步骤二:主线程看到flag是被Volatile关键字修饰的变量。则获取最新的flag变量值,此时flag = true。故输出<flag 此时为true !> 步骤三:子线程输出 Thread-0 flag = true Volatile的优点 可见性:被Volatile修饰的变量可以马上刷新主内存中的值,保证其他线程在获取时可以获取最新值,所有线程看到该变量的值均相同。 轻量级的synchronized,高并发下保证变量的可见性。 6.Volatile的缺点 1、频繁刷新主内存中变量,可能会造成性能瓶颈 2、不具备操作的原子性,不适合在对该变量的写操作依赖于变量本身自己。例如i++,并不能通过volatile来保证原子性
版权声明:本文为博主原创文章,未经博主允许不得转载。如需授权请联系微信:878799579 https://blog.csdn.net/qq_878799579/article/details/83300996 JVM系列-001-JVM监控工具 在我们安装的jdk里面的bin目录下有一个jconsole.exe程序。这就是一个JVM的监控工具。我们可以直接打开它,如果配置了环境变量,也可以在命令中直接输入jconsole命令来打开它 在控制台输入jconsole,当我们打开jconsole之后,界面如下: 本地进程中列出了本地所有运行的java进程(使用jps命令可以查看到当前所有的java进程)。如下图 注:jps进程只是在当时出现,敲击完成之后就结束了。 在jconsole中选择了进程,点击连接就能进入监控。 下图为连接后的jvm监视和管理控制台页面,此页面可以体现出堆栈使用情况。以及可以直接调用GC方法进行垃圾回收。 Jconsole界面由以下六个选项卡组成: Summary选项卡:显示JVM和被监视值的汇总信息 Memory选项卡:显示内存使用信息。 Threads选项卡:显示线程使用信息。 Classes选项卡:显示类(class)加载信息。 MBeans选项卡:显示MBeans信息 VM选项卡:显示JVM信息。 下面我们写一段测试代码来看一下对应内存消耗曲线图 import java.util.ArrayList; import java.util.List; /** * @ClassName:TestJConsole * @Description: 测试JConsole * @Author: bilaisheng * @Date 2018/10/23 6:12 */ public class TestJConsole { private byte[] bytes = new byte[1024*5]; public static void main(String[] args) { // 给使用jconsole连接的程序留下5秒时间 try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("开始测试 :"); fill(1000); } /** * =========================================================== * @Description:不断的在List中添加对象,使得堆内存消耗量增加 * @param: count * @return: void * @Author: bilaisheng * @date: 2018/10/23 6:15 * =========================================================== */ private static void fill(int count) { List jConsoleList = new ArrayList(); for (int i = 0; i <count ; i++) { // 减慢程序运行速度,否则速度过快容易抛出java.lang.OutOfMemoryError: Java heap space try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } jConsoleList.add(new TestJConsole()); } } } 监控结果如下图 大家可以看到jconsole.exe本身只有17K,其实实现功能是在jdk的lib目录下中的tools实现的此功能
<!DOCTYPE html> <html lang="zh" ng-app="myapp"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <script src="../bower_components/angular/angular.js" type="text/javascript" charset="utf-8"></script> <title>AngularJs-指令</title> <style type="text/css"> .red{color:red}; .green{color:green}; </style> </head> <body> <h3>AngularJs-$watch-01</h3> <input type="text" ng-model="username" /> {{username}} <p>改变的次数为 : {{count}}</p> <h3>AngularJs-$watch-02</h3> <div ng-repeat="item in items"> <input type="text" ng-model="item.value" />{{item.value}} </div> <p>改变的次数为 : {{rcount}}</p> <h3>AngularJs-$watchCollection</h3> <a href="javascript:void(0);" ng-click="addvalue()">add</a> <a href="javascript:void(0);" ng-click="delvalue()">del</a> <a href="javascript:void(0);" ng-click="unwatch()">unwatch</a> <div ng-repeat="item in items"> <input type="text" ng-model="item.value"/>{{item.value}} </div> <h3>AngularJs-ng-switch</h3> <!--不可见--> <div ng-controller="ifController"> <div ng-switch on="age"> <span ng-switch-when="10">青年1</span> <span ng-switch-when="20">青年2</span> <span ng-switch-when="30">青年3</span> <span ng-switch-when="40">青年4</span> <span ng-switch-default>青年5</span> </div> <h3>AngularJs-ng-if</h3> <div> <span ng-if="age>=60 && age<80">老年</span> <span ng-if="age>=40 && age<60">壮年</span> <span ng-if="age>=30 && age<40">青年</span> <span ng-if="age<10 && age<30">少年</span> </div> </div> <script type="text/javascript"> var app = angular.module("myapp",[]); // run主要作用为代表angularjs装在完毕某一些内置对象的时候 // 可能会执行以下回调函数,回调就初始化代码. /*app.run(function($rootScope){ $rootScope.username = "bilaisheng"; });*/ app.run(["$rootScope", "$log", function($rootScope, $log){ $rootScope.username="bilaisheng"; $rootScope.count = 0; $rootScope.$watch("username",function(){ $rootScope.count++; }); }]); app.run(["$rootScope","$log",function($rootScope,$log){ $rootScope.items = [ {value:1}, {value:2}, {value:3}, {value:4} ]; $rootScope.rcount = 0; $rootScope.$watch("items", function(){ $rootScope.rcount++; },true);// 为fasle: "引用监视". true: 全等监视 // watchCollection $rootScope.wcount = 0; var unWatcher = $rootScope.$watchCollection("items",function(){ $rootScope.wcount++; }); }]); app.run(["$rootScope","$log",function($rootScope,$log){ $rootScope.items = [ {value:1}, {value:2}, {value:3}, {value:4} ]; //$watchCollection 方法用来针对数组或者集合进行监视,他的性能介于全等监视和引用监视之间 //但是它并不会对数组中的每一项的属性进行监视,但是可以对数组的项目增减做出反应, $rootScope.count = 0; var unWatcher = $rootScope.$watchCollection("items",function(){ $rootScope.count++; }); //添加值 $rootScope.addvalue = function(){ $rootScope.items.push({value:5}); }; //删除值 $rootScope.delvalue = function(){ $rootScope.items.splice(0,1); }; //删除监听 $rootScope.unwatch = function(){ unWatcher();//解除监听 }; }]); /** * 1: 选中的元素: * checkbox radio * ng-checked = true/false * select * ng-selected = true/false * 禁止选择: * ng-disabled=true/false * 2:关于指令如果调用作用域属性和方法的时候是不需要表达式的 * */ app.controller("ifController",function($scope){ $scope.age = 30; }); </script> </body> </html>
<!DOCTYPE html> <html lang="zh" ng-app="myapp"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <script src="../bower_components/angular/angular.js" type="text/javascript" charset="utf-8"></script> <title>AngularJs-作用域继承</title> </head> <body> <div ng-controller="outController"> <h1>{{username}}</h1> <div ng-controller="innerController"> <h1>{{username}} {{realname}}</h1> </div> <div ng-controller="innerController2"> <h1>{{username}} {{realname}}</h1> </div> </div> <script type="text/javascript"> var app = angular.module("myapp",[]); app.controller("outController", function($scope){ $scope.username="out name"; }); app.controller("innerController", function($scope){ $scope.username="innerController name"; }); app.controller("innerController2", function($scope){ $scope.username="innerController2 name"; }); // call apply 寄生继承 function Part(name, age){ this.name = name ; this.age = age ; this.eat = function(){ console.log("Part eat"); }; }; function Children(name, age){ Part.call(this, name, age); this.sleep = function(){ console.log("Children sleeping "); } } var children = new Children("bilaisheng", 18); console.log(children.name); console.log(children.age); children.eat(); children.sleep(); // 对象之间实例继承 function Person(name, age){ this.name = name; this.age = age; this.arr =[]; } //person的属性和方法是来自两个部分: //1:一个部分是来自构造函数(复制过来,对象自有属性 obj.hasOwnProperty("name")) //2:来自原型对象(_proto_)进行的原型映射 var person = new Person("bilaisheng", 18); // 单对象继承 var student = Object.create(person); student.arr.push("javascript"); student.name = "zhangsan"; console.log(student.name+"--->"+student.age+"--->"+student.arr); console.log(person.name+"--->"+person.age+"--->"+person.arr); </script> </body> </html>
<!DOCTYPE html> <html lang="zh" ng-app="myapp"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <script src="../bower_components/angular/angular.js" type="text/javascript" charset="utf-8"></script> <title>AngularJs-模拟购物车</title> <style type="text/css"> *{margin: 0;padding: 0;} body{margin:50px;} .tab{border-collapse: collapse;width: 100%;} th,td{border:1px solid #ccc;padding: 5px; text-align: text;} </style> </head> <body> <table class="tab" ng-controller="shopController"> <thead> <tr> <th>ID</th> <th>名称</th> <th>金额</th> <th>数量</th> <th>小计</th> </tr> <tr ng-repeat="data in cdatas"> <td>{{data.id}}</td> <td>{{data.name}}</td> <td><input type="text" ng-model="data.price"/></td> <td><input type="text" ng-model="data.num"/></td> <td>{{data.price * data.num}}</td> </tr> <tfoot> <tr> <td colspan="10" style="text-align:right;padding: 20px;"> <input type="button" ng-click="totals()" value="计算总金额" /> <div>总计为:{{totals()}}元</div> </td> </tr> </tfoot> </thead> </table> <script type="text/javascript"> var app = angular.module("myapp",[]); app.controller("shopController",function($scope){ $scope.cdatas = [ {id:1,name:"苹果1",price:1,num:1,total:2}, {id:2,name:"苹果2",price:2,num:2,total:4}, {id:3,name:"苹果3",price:3,num:3,total:6}, {id:4,name:"苹果4",price:4,num:4,total:8}, {id:5,name:"苹果5",price:5,num:5,total:10} ]; $scope.totals = function(){ var total = 0; for (var i = 0;i < $scope.cdatas.length; i++) { total += $scope.cdatas[i].price * $scope.cdatas[i].num; } return total; }; }); </script> </body> </html>
<!DOCTYPE html> <html lang="zh" ng-app="myapp"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <script src="../bower_components/angular/angular.js" type="text/javascript" charset="utf-8"></script> <title>AngularJs-模拟登陆</title> </head> <body> <form action="" id="loginForm" ng-controller="loginController"> <p>用户名:<input type="text" ng-model="username" /></p> <p>密码:<input type="text" ng-model="password" /></p> <p><input type="button" ng-click="login($event)" value="登陆" /></p> </form> <script type="text/javascript"> var app = angular.module("myapp",[]); app.controller("loginController",function($scope){ $scope.username = "bilaisheng"; $scope.password = "123456"; $scope.login = function(e){ var btndom = e.target; btndom.value = "登陆用户"; var username = $scope.username; var password = $scope.password; if (username == "bilaisheng" && password == "123456") { alert("登陆成功"); } else{ alert("登陆失败"); } }; }); </script> </body> </html>
<!DOCTYPE html> <html lang="zh" ng-app="myapp"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <script src="../bower_components/angular/angular.js" type="text/javascript" charset="utf-8"></script> <title>AngularJs-数据的双向绑定</title> </head> <body ng-init="username='bilaisheng';address='北京';"> <h3>for TestController</h3> <ul ng-controller="TestController"> <li ng-repeat="room in classroom"> {{room.name}}-->{{room.age}}-->{{username}}-->{{address}} </li> </ul> <h3>for TestController2</h3> <ul ng-controller="TestController2"> <li ng-repeat="room in classroom"> {{room.name}}-->{{room.age}}-->{{username}}-->{{address}} </li> </ul> <h3>for ng-bind</h3> <div>用户名:<input type="text" ng-model="username" /></div> <div>你输入的用户名是:{{username}}</div> <div>你输入的用户名是:<span ng-bind="username"></span></div> <div>你输入的用户名是:<span class="ng-bind:username"></span></div> <script type="text/javascript"> // 初始化一个angularjs的代理对象 var app = angular.module("myapp",[]); // for TestController app.controller("TestController",function($scope,$rootScope,$log){ $scope.classroom=[ {name:"张三",age:20}, {name:"李四",age:21}, {name:"王五",age:22}, {name:"赵六",age:23} ]; $scope.username="李七"; }); // for TestController2 app.controller("TestController2",function($scope,$rootScope,$log){ $scope.classroom=[ {name:"张三",age:20}, {name:"李四",age:21}, {name:"王五",age:22}, {name:"赵六",age:23} ]; $scope.username="李七"; }); /** * ng-init : 初始化数据 * ng-repeat: 迭代数组和对象,语法 * ng-repeat="变量 in 对象/数组" -- 循环 * eg : <div ng-repeat"变量 in 对象/数组"></div> * * AngularJs双向数据绑定: 能够大幅度减少对dom元素的操作. */ </script> </body> </html>
<!DOCTYPE html> <html lang="zh" ng-app> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <script src="../bower_components/angular/angular.js" type="text/javascript" charset="utf-8"></script> <title>{person.name}}-AngularJs-表达式和作用域</title> </head> <body ng-init="name='bilaisheng';age=10"> {{name}} {{age}} <div ng-init="person={name:'bilaisheng',age:18}"></div> {{person.name}} {{person.age}} <div ng-init="arr = [1,2,3,4,5,6,7,8,9]"></div> <h1>数组第一个元素:{{arr[0]}}</h1> <h1>数组最后一个元素{{arr[arr.length-1]}}</h1> <h1>数组的长度{{arr.length}}</h1> <ol ng-repeat="c in arr"> {{c}} </ol> <div ng-init="carr = [{username:'bilaisheng',age:18},{username:'three',age:30}]"></div> <h1>数组第一个元素:{{carr[0].username}}</h1> <h1>数组最后一个元素:{{carr[carr.length-1].age}}</h1> <ul ng-repeat="c in carr"> <li>{{c.username}}--->{{c.age}}</li> </ul> <script type="text/javascript"> /** * 1. 表达式和作用域 * ng-init : 该指令用以初始化一些作用域的数据,它的数据挂载到全局作用域$rootScope */ </script> </body> </html>
<!DOCTYPE html> <html lang="zh" ng-app> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <script src="../bower_components/angular/angular.js" type="text/javascript" charset="utf-8"></script> <title>AngularJs-HelloWorld</title> </head> <body> <div>{{"Hello World!"}}</div> <div>{{"Hello AngularJs!"}}</div> <script type="text/javascript"> /** * ng-app : 内置一个指令,可以出现在任意位置,主要是代表angularjs的启动命令。 * AngularJs 从ng-app指令从所在标签的开始到结束标签之间所有dom元素由AngularJs管理 * 一般加在html上。 表示整个页面均被AngularJs管理。 * * {{}} 是AngularJs的一个表达形式。 有两个花括号 * 主要作用:用于作用于$rootScope和$scope数据内容渲染和填充。 */ </script> </body> </html>
在设计一种HDFS模式时,首先应该决定文件的位置.标准化的位置会使得团队之间更容易查找和共享数据. 推荐HDFS目录结构实例.目录结构简化了不同组和用户的权限分配 /user/{username} 只属于特定用户的数据,JAR包和配置文件.通常是用户在试验中使用的非正式数据,不属于业务流程./user下的目录通常只能由所有者进行读取和写入 /etl ETL(Extract, Transform and Load,提取,转化,加载)工作流正在处理的.处于不同阶段的数据./etl目录由ETL过程(通常是在各自的user目录下进行)与ETL团队的成员读取和写入.拥有ETL过程的不同组别(如业务分析,欺诈识别,以及市场营销)在/etl目录树中都有对应的子目录. /tmp 工具生成或者用户共享的临时数据.该目录通常通过程序自动清除,不会存储生命周期长的数据.通常每个人都能读取或写入该目录 /data 经过处理并且在整个组织内共享的数据集.这些通常是待分析数据的重要来源,可以促成业务决策,所以不能不分身份角色,任人读取和写入.通常用户只能读取数据,数据由自动化的ETL过程写入.而且需要审计./data目录下的数据通常对于业务非常重要,所以一般只允许自动化的ETL过程写入数据,改变都是要受到控制和审计的.不同的业务团队对于/data目录下的目录拥有不同的读取权限. /app 几乎囊括Hadoop应用运行所需要的一些,但不包括数据,这里有Jar文件,OOzie工作流定义,Hive HQL文件,等等.应用的代码目录/app用于存储应用所需要的依赖.各版本的目录应该类似于如下结构: /app/<组>/<应用>/<版本>/<包目录>/<包> /metadata 存储元数据,尽管大多数表元数据都存储在Hive metastore中,但是还是可能会有一些元数据(如Avro模式文件)可能需要存储在HDFS中.该目录是存储此类元数据的最佳位置.该目录通常对ETL任务可读,而采集数据到Hadoop中的用户(如Sqoop用户)则拥有写权限.
列式系统可提供的优势对于查询内容之外的列,不必执行I/O和解压(若适用)操作非常适合仅访问小部分列的查询.如果访问的列很多,则行存格式更为合适相比由多行构成的数据块,列内的信息熵更低,所以从压缩角度来看,列式存储通常会非常高效.换句话说,同一列中的数据比行存数据块中的数据更为相似.当某一列的取值不多是,行存与列存在压缩效果上的差异尤为显著数据仓库类型的应用需要在极大的数据集上对某些特定的列进行聚合操作,而列式存储格式通常很适合此类应用场景显然,列式文件格式也常常出现在Hadoop的应用中.Hadoop支持的列式格式包括一度广泛应用为Hive格式的RPFile,以及其他格式,如ORC(Optimized Row Columnar),以及Parquet等. RCFileRCFile专为高效处理MapReduce应用程序而开发,尽管在时间过程中,它一般只作为Hive存储格式使用.RCFile的开发旨在快速加载和查询数据,以及更高效的利用存储空间.RCFile格式将文件按行进行分片,每个分片按列存储. 与SequenceFile相比,RCFile格式在查询与压缩性能方面有很多优势.但这种格式也存在一些缺陷,会阻碍查询时间和压缩空间的进一步优化.这些问题很多都可以由更为新型的列式存储格式(比如ORC与Parquet)化解.大部分不断涌现的应用很有可能放弃使用RCFile,改用新型的列存格式.不过,RCFile目前仍然是Hive中常用的存储格式. ORCORC格式的开发初中是为了弥补RCFile格式方面的一些不足,尤其是查询性能和存储效率方面的缺陷.相比RCFile,ORC格式在很多方面都有显著进步,其特点和优势如下. 通过特定类型(type-specific)的reader与writer提供轻量级的,在线的(always-on)压缩.ORC还支持使用zlib,LZO和Snappy压缩算法提供进一步的压缩能够将谓词下推至存储层,仅返回查询所需要的数据支持Hive类型的模型,包括新增的decimal类型与复杂类型.支持分片ParquetParquet和ORC有很多相同的设计目标,但是Parquet有意成为Hadoop上的通用存储格式.Parquet的目标是成为能够普遍应用于不同MapReduce接口(如Java,Hive与Pig)的格式,同事也要适应其他处理引擎(如Impala与Spark).Parquet的优势如下,其中很多优势与ORC相同 与ORC文件类似,Parquet允许金返回需要的数据字段,因此减少了I/O,提升了性能提供高效的压缩,可以在每列上指定压缩算法设计的初衷便是支持复杂的嵌套数据结构在文件尾部有完整的元数据信息存储,所以Parquet文件是自描述的完全支持通过Avro和Thrift API写入与读取使用可扩展的高效编码模式,比如 按位封装(bit-packaging)和游程编码(Run Length Encoding,RLE)不同文件格式的失败行为不同文件格式之间一个重要的差异在于如何处理数据错误,某些格式可以更好的处理文件损坏. 列式格式虽然高效,但是在错误处理方面表现并不是很好,这是因为文件损毁可能导致行不完全.序列化格式在第一个出错的行之前能够正常读取,但是在随后的行中无法恢复Avro的错误处理能力最强,出现错误记录时,读操作将在下一个同步点(syncpoint)继续,所以错误只会影响文件的一部分
序列化存储指的是将数据结构转化为字节流的过程,一般用于数据存储或者网络传输.与之相反, 反序列化是将字节流转化为数据结果的过程.序列化是分布处理系统(比如Hadoop)的核心,原因在于他能对数据进行转化,形成一种格式.使用了这样的格式之后,数据可以有效的存储,也能通过网络连接进行传输.序列化通常与分布式系统中数据处理的两个方面紧密连接:进程间的通信(比如他远程过程调用,即Remote Prucedure Call RPC),以及数据存储. Hadoop主要采用的序列化格式为Writables.Writables的特点是紧密,快速.但是脱离Java语言不便于扩展和使用.不过Hadoop生态系统中也有越发普及的其他序列化的框架,包括Thrift,Protocol Buffers 与Avro. 其中Avro的适用性最好,因为它创建的初中就是解除Hadoop Writables的限制.1 Thrift Thrift 是Facebook公司开发的框架,用于实现跨语言提供服务接口.Thrift使用接口定义语言(Interface Definition Language, IDL)定义服务接口,而且依据IDL文件自动生成桩代码(stub code),使用这些代码的RPC客户端与服务器,能够跨平台通信. 2 Protocol Buffers Protocol Buffers(prorobuf)格式由Google公司开发,用于在不同语言编写的服务之间完成数据交换 ,与Thrift类似,Protobuf的结构由一个IDL文件定义,IDL用于为不同的语言创建桩代码.与Thrift类似的是,Protocol Buffers 不支持记录的内部压缩,不可分片,而且缺少MapReduce的原生支持.但是,同样与Thrift类似,Elephant Bird项目可以用于编码protobuf记录,支持MapReduce,压缩以及分片. 3 Avro Avro是一种和语言无关的数据序列化系统,其设计初衷是解决Hadoop Writables的主要缺点,即缺少跨语言的可移植性支持.与Thrift和Protocol Buffers相同的是,Avr的数据描述也无关语言.与Thrift和Protocol Buffers不同的是,Avro可以选择生成代码,也可以选择不生成代码.因为Avro将模式存储于每个文件的头部,所以每个文件都是自描述的(self-documenting).Avro文件都很容易读取,即使是用一种语言写入数据,而另外一种语言类读取,也没有影响.Avro为MapReduce提供了更好的原生支持.因为Avro的数据可压缩可分片.Avro的另一个重要特点是支持模式演进(schema evolution),这一特点使得Avro比SequenceFile更适合Hadoop应用.也就是说,读取文件的模式不需要与邪恶如文件的模式严格匹配.于是,当需求发生变更的时候,模式中可以添加新的字段 Avro通常都是以JSON格式定义,但是也可以用Avro IDL定义,如前所述,模式存储于文件的头部,是文件元数据的一部分.除了元数据,文件头部还八廓一个唯一的同步标志.与SequenceFile类似,这个同步标志用于隔开文件中的数据块.从而使Avro文件支持分片.每个Avro文件的头部后面都有一系列的数据块,包含序列化后的Avro对象.这些数据块可以压缩.而且,各种数据以原格式存储在这些数据块中,这也为压缩提供了额外的帮助. Avro定义了少量的基本类型.包括 Boolean int float和string .它也支持array map和enum等复杂类型
标准文件格式可以指文本格式,也可以指二进制文件类型.前者包括逗号分隔值(Comma-Separated Value,CSV和可扩展的标记语言文本(Extensible Markup Language. XML)格式 , 后者包括图像. Hadoop最强大的一个功能就是可以存储任何一种格式的数据. 原始的数据格式能够在线访问,数据完全保真.1 文本数据 Hadoop非常常见的一个应用是日志(如网络日志和服务器日志)存储于分析.文本数据当然也可以是其他很多格式,包括CSV文件和邮件之类的非结构化数据.在Hadoop中存储文本数据时,主要是考虑文件在系统中的组织形式.另外,因为文本文件会非常快速的消耗Hadoop集群的存储空间 ,所以虽好对其压缩.还有一点需要谨记,使用文本格式存储数据会因类型转换带来额外开销 数据的使用方式会影响压缩格式的选择.如果是为了存档,可能会选择压缩率最高的压缩方式.如果数据需要使用MapReduce进行处理,那么可能选择一种支持分片的压缩格式.可分片格式允许Hadoop将文件分成不同分片进行处理,这对数据的高效并行处理至关重要. 在许多(甚至大多数)场景中,运用SequenceFile, Avro等容器格式都能带来益处,因此容器格式是文本等大部分文件类型的优选格式.此外,容易格式还能够支持可分片的压缩. 2 结构化文本数据 XML和JSON这样的结构化格式是文本文件格式中比较特殊的一种. XML和JSON文件比较难分片,Hadoop也没有为这种格式提供内置的InputFormat.在Hadoop中,JSON格式比XML跟俺处理,因为这里没有标记可以标识记录的开始与结束.处理这类格式时,你可以有一下两个选择进行参考: 使用类似于Avro的容器格式.将数据转化为Avro的内容,从而为数据存储与数据处理提供更加紧密,有效的方法.使用处理XML或JSON文件的专用库,比如,说到XML, Pig的PiggyBank库(https://cwiki.apache.org/confluence/display/PIG/PiggyBank)中就有XMLLoader可供使用.而JSON则可以利用Elephant Bird 项目 (https://github.com/twitter/elephant-bird)提供的LzoJsonInputFormat.3 二进制数据 Hadoop中最常见的源数据格式是文本. 但Hadoop也可以处理二进制文件(比如图像).对于Hadoop上的大多数应用场景来说,二进制文件的存储和处理最好能使用Sequencefile之类的容器格式.如果二进制数据的每个分片大雨64MB,则可以考虑使用该二进制数据自己的格式,无需使用容器格式
文件格式 Hadoop支持多种面向数据存储的文件格式,包括纯文本和Hadoop特有的格式,如SequenceFile.还有一些更加复杂但功能更加丰富的格式可供选择,如Avro与Parquet.不同的格式具有不同的优势.任何一种格式都有适合的应用或者数据源类型.也可以在Hadoop中自己定制化文件格式 压缩格式 Hadoop上常用的压缩编解码格式具有不同的特点,比如,一些编解码格式压缩和解压的速度较快,但是压缩效果不好,而有些编解码格式能将文件压缩的更小,但是压缩和解压的时间都比较长,这种情况下 ,CPU的负担加重.在Hadoop上存储数据时,要考虑的另一个重要因素是压缩后的数据是否支持切片. 数据存储系统 尽管Hadoop中的所有数据最终存储在HSFD上,但是仍然需要选择实际的存储管理器(Storage Manager),比如你可以选择Hbase,也可以直接用HDFS存储数据.另外,Hive和Impala这样的工具能够为Hadoop中 的数据定义额外的结构信息
import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; public class CompletableFuture1 { public static void main(String[] args) throws ExecutionException, InterruptedException { CompletableFuture<String> future = new CompletableFuture<>(); future.complete("42"); future .thenAccept(System.out::println) .thenAccept(v -> System.out.println("done")); } }
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.LongAccumulator; import java.util.function.LongBinaryOperator; import java.util.stream.IntStream; public class LongAccumulator { public static void main(String[] args) { testAccumulate(); } private static void testAccumulate() { LongBinaryOperator op = (x, y) -> 2 * x + y; LongAccumulator accumulator = new LongAccumulator(op, 1L); ExecutorService executor = Executors.newFixedThreadPool(2); IntStream.range(0, 10) .forEach(i -> executor.submit(() -> accumulator.accumulate(i))); ConcurrentUtils.stop(executor); System.out.format("Add: %d\n", accumulator.getThenReset()); } }
import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; public class ConcurrentUtils { public static void stop(ExecutorService executor) { try { executor.shutdown(); executor.awaitTermination(60, TimeUnit.SECONDS); } catch (InterruptedException e) { System.err.println("termination interrupted"); } finally { if (!executor.isTerminated()) { System.err.println("killing non-finished tasks"); } executor.shutdownNow(); } } public static void sleep(int seconds) { try { TimeUnit.SECONDS.sleep(seconds); } catch (InterruptedException e) { throw new IllegalStateException(e); } } }
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ForkJoinPool; public class ConcurrentHashMap1 { public static void main(String[] args) { System.out.println("Parallelism: " + ForkJoinPool.getCommonPoolParallelism()); testForEach(); testSearch(); testReduce(); } private static void testReduce() { ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>(); map.putIfAbsent("foo", "bar"); map.putIfAbsent("han", "solo"); map.putIfAbsent("r2", "d2"); map.putIfAbsent("c3", "p0"); String reduced = map.reduce(1, (key, value) -> key + "=" + value, (s1, s2) -> s1 + ", " + s2); System.out.println(reduced); } private static void testSearch() { ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>(); map.putIfAbsent("foo", "bar"); map.putIfAbsent("han", "solo"); map.putIfAbsent("r2", "d2"); map.putIfAbsent("c3", "p0"); System.out.println("\nsearch()\n"); String result1 = map.search(1, (key, value) -> { System.out.println(Thread.currentThread().getName()); if (key.equals("foo") && value.equals("bar")) { return "foobar"; } return null; }); System.out.println(result1); System.out.println("\nsearchValues()\n"); String result2 = map.searchValues(1, value -> { System.out.println(Thread.currentThread().getName()); if (value.length() > 3) { return value; } return null; }); System.out.println(result2); } private static void testForEach() { ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>(); map.putIfAbsent("foo", "bar"); map.putIfAbsent("han", "solo"); map.putIfAbsent("r2", "d2"); map.putIfAbsent("c3", "p0"); map.forEach(1, (key, value) -> System.out.printf("key: %s; value: %s; thread: %s\n", key, value, Thread.currentThread().getName())); // map.forEach(5, (key, value) -> System.out.printf("key: %s; value: %s; thread: %s\n", key, value, Thread.currentThread().getName())); System.out.println(map.mappingCount()); } }
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.IntStream; public class Atomic1 { private static final int NUM_INCREMENTS = 1000; private static AtomicInteger atomicInt = new AtomicInteger(0); public static void main(String[] args) { testIncrement(); testAccumulate(); testUpdate(); } private static void testUpdate() { atomicInt.set(0); ExecutorService executor = Executors.newFixedThreadPool(2); IntStream.range(0, NUM_INCREMENTS) .forEach(i -> { Runnable task = () -> atomicInt.updateAndGet(n -> n + 2); executor.submit(task); }); ConcurrentUtils.stop(executor); System.out.format("Update: %d\n", atomicInt.get()); } private static void testAccumulate() { atomicInt.set(0); ExecutorService executor = Executors.newFixedThreadPool(2); IntStream.range(0, NUM_INCREMENTS) .forEach(i -> { Runnable task = () -> atomicInt.accumulateAndGet(i, (n, m) -> n + m); executor.submit(task); }); ConcurrentUtils.stop(executor); System.out.format("Accumulate: %d\n", atomicInt.get()); } private static void testIncrement() { atomicInt.set(0); ExecutorService executor = Executors.newFixedThreadPool(2); IntStream.range(0, NUM_INCREMENTS) .forEach(i -> executor.submit(atomicInt::incrementAndGet)); ConcurrentUtils.stop(executor); System.out.format("Increment: Expected=%d; Is=%d\n", NUM_INCREMENTS, atomicInt.get()); } }
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.stream.IntStream; public class Synchronized2 { private static final int NUM_INCREMENTS = 10000; private static int count = 0; public static void main(String[] args) { testSyncIncrement(); } private static void testSyncIncrement() { count = 0; ExecutorService executor = Executors.newFixedThreadPool(2); IntStream.range(0, NUM_INCREMENTS) .forEach(i -> executor.submit(Synchronized2::incrementSync)); ConcurrentUtils.stop(executor); System.out.println(count); } private static void incrementSync() { synchronized (Synchronized2.class) { count = count + 1; } } }
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.stream.IntStream; public class Synchronized1 { private static final int NUM_INCREMENTS = 10000; private static int count = 0; public static void main(String[] args) { testSyncIncrement(); testNonSyncIncrement(); } private static void testSyncIncrement() { count = 0; ExecutorService executor = Executors.newFixedThreadPool(2); IntStream.range(0, NUM_INCREMENTS) .forEach(i -> executor.submit(Synchronized1::incrementSync)); ConcurrentUtils.stop(executor); System.out.println(" Sync: " + count); } private static void testNonSyncIncrement() { count = 0; ExecutorService executor = Executors.newFixedThreadPool(2); IntStream.range(0, NUM_INCREMENTS) .forEach(i -> executor.submit(Synchronized1::increment)); ConcurrentUtils.stop(executor); System.out.println("NonSync: " + count); } private static synchronized void incrementSync() { count = count + 1; } private static void increment() { count = count + 1; } }
import java.util.Arrays; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; public class Executors3 { public static void main(String[] args) throws InterruptedException, ExecutionException { test1(); // test2(); // test3(); // test4(); // test5(); } private static void test5() throws InterruptedException, ExecutionException { ExecutorService executor = Executors.newWorkStealingPool(); List<Callable<String>> callables = Arrays.asList( callable("task1", 2), callable("task2", 1), callable("task3", 3)); String result = executor.invokeAny(callables); System.out.println(result); executor.shutdown(); } private static Callable<String> callable(String result, long sleepSeconds) { return () -> { TimeUnit.SECONDS.sleep(sleepSeconds); return result; }; } private static void test4() throws InterruptedException { ExecutorService executor = Executors.newWorkStealingPool(); List<Callable<String>> callables = Arrays.asList( () -> "task1", () -> "task2", () -> "task3"); executor.invokeAll(callables) .stream() .map(future -> { try { return future.get(); } catch (Exception e) { throw new IllegalStateException(e); } }) .forEach(System.out::println); executor.shutdown(); } private static void test3() { ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); Runnable task = () -> { try { TimeUnit.SECONDS.sleep(2); System.out.println("Scheduling: " + System.nanoTime()); } catch (InterruptedException e) { System.err.println("task interrupted"); } }; executor.scheduleWithFixedDelay(task, 0, 1, TimeUnit.SECONDS); } private static void test2() { ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); Runnable task = () -> System.out.println("Scheduling: " + System.nanoTime()); int initialDelay = 0; int period = 1; executor.scheduleAtFixedRate(task, initialDelay, period, TimeUnit.SECONDS); } private static void test1() throws InterruptedException { ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); Runnable task = () -> System.out.println("Scheduling: " + System.nanoTime()); int delay = 3; ScheduledFuture<?> future = executor.schedule(task, delay, TimeUnit.SECONDS); TimeUnit.MILLISECONDS.sleep(1337); long remainingDelay = future.getDelay(TimeUnit.MILLISECONDS); System.out.printf("Remaining Delay: %sms\n", remainingDelay); } }
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class Executors2 { public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException { // test1(); // test2(); test3(); } private static void test3() throws InterruptedException, ExecutionException, TimeoutException { ExecutorService executor = Executors.newFixedThreadPool(1); Future<Integer> future = executor.submit(() -> { try { TimeUnit.SECONDS.sleep(2); return 123; } catch (InterruptedException e) { throw new IllegalStateException("task interrupted", e); } }); future.get(1, TimeUnit.SECONDS); } private static void test2() throws InterruptedException, ExecutionException { ExecutorService executor = Executors.newFixedThreadPool(1); Future<Integer> future = executor.submit(() -> { try { TimeUnit.SECONDS.sleep(1); return 123; } catch (InterruptedException e) { throw new IllegalStateException("task interrupted", e); } }); executor.shutdownNow(); future.get(); } private static void test1() throws InterruptedException, ExecutionException { ExecutorService executor = Executors.newFixedThreadPool(1); Future<Integer> future = executor.submit(() -> { try { TimeUnit.SECONDS.sleep(1); return 123; } catch (InterruptedException e) { throw new IllegalStateException("task interrupted", e); } }); System.out.println("future done: " + future.isDone()); Integer result = future.get(); System.out.println("future done: " + future.isDone()); System.out.print("result: " + result); executor.shutdownNow(); } }
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class Executors1 { public static void main(String[] args) { test1(3); // test1(7); } private static void test1(long seconds) { ExecutorService executor = Executors.newSingleThreadExecutor(); executor.submit(() -> { try { TimeUnit.SECONDS.sleep(seconds); String name = Thread.currentThread().getName(); System.out.println("task finished: " + name); } catch (InterruptedException e) { System.err.println("task interrupted"); } }); stop(executor); } static void stop(ExecutorService executor) { try { System.out.println("attempt to shutdown executor"); executor.shutdown(); executor.awaitTermination(5, TimeUnit.SECONDS); } catch (InterruptedException e) { System.err.println("termination interrupted"); } finally { if (!executor.isTerminated()) { System.err.println("killing non-finished tasks"); } executor.shutdownNow(); System.out.println("shutdown finished"); } } }
import java.util.Optional; import java.util.function.Supplier; public class Optional2 { static class Outer { Nested nested = new Nested(); public Nested getNested() { return nested; } } static class Nested { Inner inner = new Inner(); public Inner getInner() { return inner; } } static class Inner { String foo = "boo"; public String getFoo() { return foo; } } public static void main(String[] args) { test1(); test2(); test3(); } public static <T> Optional<T> resolve(Supplier<T> resolver) { try { T result = resolver.get(); return Optional.ofNullable(result); } catch (NullPointerException e) { return Optional.empty(); } } private static void test3() { Outer outer = new Outer(); resolve(() -> outer.getNested().getInner().getFoo()) .ifPresent(System.out::println); } private static void test2() { Optional.of(new Outer()) .map(Outer::getNested) .map(Nested::getInner) .map(Inner::getFoo) .ifPresent(System.out::println); } private static void test1() { Optional.of(new Outer()) .flatMap(o -> Optional.ofNullable(o.nested)) .flatMap(n -> Optional.ofNullable(n.inner)) .flatMap(i -> Optional.ofNullable(i.foo)) .ifPresent(System.out::println); } }
import java.util.Optional; public class Optional1 { public static void main(String[] args) { Optional<String> optional = Optional.of("bam"); optional.isPresent(); // true optional.get(); // "bam" optional.orElse("fallback"); // "bam" optional.ifPresent((s) -> System.out.println(s.charAt(0))); // "b" } }
import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; public class Concurrency1 { public static void main(String[] args) { ConcurrentHashMap<Integer, UUID> concurrentHashMap = new ConcurrentHashMap<>(); for (int i = 0; i < 100; i++) { concurrentHashMap.put(i, UUID.randomUUID()); } int threshold = 1; concurrentHashMap.forEachValue(threshold, System.out::println); concurrentHashMap.forEach((id, uuid) -> { if (id % 10 == 0) { System.out.println(String.format("%s: %s", id, uuid)); } }); UUID searchResult = concurrentHashMap.search(threshold, (id, uuid) -> { if (String.valueOf(uuid).startsWith(String.valueOf(id))) { return uuid; } return null; }); System.out.println(searchResult); } }
import java.lang.annotation.ElementType; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; public class Annotations1 { @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) @interface MyAnnotation { } @Retention(RetentionPolicy.RUNTIME) @interface Hints { Hint[] value(); } @Repeatable(Hints.class) @Retention(RetentionPolicy.RUNTIME) @interface Hint { String value(); } @Hint("hint1") @Hint("hint2") class Person { } public static void main(String[] args) { Hint hint = Person.class.getAnnotation(Hint.class); System.out.println(hint); // null Hints hints1 = Person.class.getAnnotation(Hints.class); System.out.println(hints1.value().length); // 2 Hint[] hints2 = Person.class.getAnnotationsByType(Hint.class); System.out.println(hints2.length); // 2 } }
import java.util.HashMap; import java.util.function.BiConsumer; public class Lambda5 { //Pre-Defined Functional Interfaces public static void main(String... args) { //BiConsumer Example BiConsumer<String,Integer> printKeyAndValue = (key,value) -> System.out.println(key+"-"+value); printKeyAndValue.accept("One",1); printKeyAndValue.accept("Two",2); System.out.println("##################"); //Java Hash-Map foreach supports BiConsumer HashMap<String, Integer> dummyValues = new HashMap<>(); dummyValues.put("One", 1); dummyValues.put("Two", 2); dummyValues.put("Three", 3); dummyValues.forEach((key,value) -> System.out.println(key+"-"+value)); } }
import java.util.Comparator; import java.util.Objects; import java.util.UUID; import java.util.concurrent.Callable; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; public class Lambda3 { @FunctionalInterface interface Fun { void foo(); } public static void main(String[] args) throws Exception { // Predicates Predicate<String> predicate = (s) -> s.length() > 0; predicate.test("foo"); // true predicate.negate().test("foo"); // false Predicate<Boolean> nonNull = Objects::nonNull; Predicate<Boolean> isNull = Objects::isNull; Predicate<String> isEmpty = String::isEmpty; Predicate<String> isNotEmpty = isEmpty.negate(); // Functions Function<String, Integer> toInteger = Integer::valueOf; Function<String, String> backToString = toInteger.andThen(String::valueOf); backToString.apply("123"); // "123" // Suppliers Supplier<Person> personSupplier = Person::new; personSupplier.get(); // new Person // Consumers Consumer<Person> greeter = (p) -> System.out.println("Hello, " + p.firstName); greeter.accept(new Person("Luke", "Skywalker")); // Comparators Comparator<Person> comparator = (p1, p2) -> p1.firstName.compareTo(p2.firstName); Person p1 = new Person("John", "Doe"); Person p2 = new Person("Alice", "Wonderland"); comparator.compare(p1, p2); // > 0 comparator.reversed().compare(p1, p2); // < 0 // Runnables Runnable runnable = () -> System.out.println(UUID.randomUUID()); runnable.run(); // Callables Callable<UUID> callable = UUID::randomUUID; callable.call(); } }
public class Lambda2 { @FunctionalInterface public static interface Converter<F, T> { T convert(F from); } static class Something { String startsWith(String s) { return String.valueOf(s.charAt(0)); } } interface PersonFactory<P extends Person> { P create(String firstName, String lastName); } public static void main(String[] args) { Converter<String, Integer> integerConverter1 = (from) -> Integer.valueOf(from); Integer converted1 = integerConverter1.convert("123"); System.out.println(converted1); // result: 123 // method reference Converter<String, Integer> integerConverter2 = Integer::valueOf; Integer converted2 = integerConverter2.convert("123"); System.out.println(converted2); // result: 123 Something something = new Something(); Converter<String, String> stringConverter = something::startsWith; String converted3 = stringConverter.convert("Java"); System.out.println(converted3); // result J // constructor reference PersonFactory<Person> personFactory = Person::new; Person person = personFactory.create("Peter", "Parker"); } }
public class Lambda4 { static int outerStaticNum; int outerNum; void testScopes() { int num = 1; Lambda2.Converter<Integer, String> stringConverter = (from) -> String.valueOf(from + num); String convert = stringConverter.convert(2); System.out.println(convert); // 3 Lambda2.Converter<Integer, String> stringConverter2 = (from) -> { outerNum = 13; return String.valueOf(from); }; String[] array = new String[1]; Lambda2.Converter<Integer, String> stringConverter3 = (from) -> { array[0] = "Hi there"; return String.valueOf(from); }; stringConverter3.convert(23); System.out.println(array[0]); } public static void main(String[] args) { new Lambda4().testScopes(); } }
import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Optional; public class Lambda1 { public static void main(String[] args) { List<String> names = Arrays.asList("peter", "anna", "mike", "xenia"); Collections.sort(names, new Comparator<String>() { @Override public int compare(String a, String b) { return b.compareTo(a); } }); Collections.sort(names, (String a, String b) -> { return b.compareTo(a); }); Collections.sort(names, (String a, String b) -> b.compareTo(a)); Collections.sort(names, (a, b) -> b.compareTo(a)); System.out.println(names); names.sort(Collections.reverseOrder()); System.out.println(names); List<String> names2 = Arrays.asList("peter", null, "anna", "mike", "xenia"); names2.sort(Comparator.nullsLast(String::compareTo)); System.out.println(names2); List<String> names3 = null; Optional.ofNullable(names3).ifPresent(list -> list.sort(Comparator.naturalOrder())); System.out.println(names3); } }
import java.util.concurrent.TimeUnit; public class Threads1 { public static void main(String[] args) { test1(); // test2(); // test3(); } private static void test3() { Runnable runnable = () -> { try { System.out.println("Foo " + Thread.currentThread().getName()); TimeUnit.SECONDS.sleep(1); System.out.println("Bar " + Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } }; Thread thread = new Thread(runnable); thread.start(); } private static void test2() { Runnable runnable = () -> { try { System.out.println("Foo " + Thread.currentThread().getName()); Thread.sleep(1000); System.out.println("Bar " + Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } }; Thread thread = new Thread(runnable); thread.start(); } private static void test1() { Runnable runnable = () -> { String threadName = Thread.currentThread().getName(); System.out.println("Hello " + threadName); }; runnable.run(); Thread thread = new Thread(runnable); thread.start(); System.out.println("Done!"); } }
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.StampedLock; public class Lock5 { public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(2); StampedLock lock = new StampedLock(); executor.submit(() -> { long stamp = lock.tryOptimisticRead(); try { System.out.println("Optimistic Lock Valid: " + lock.validate(stamp)); ConcurrentUtils.sleep(1); System.out.println("Optimistic Lock Valid: " + lock.validate(stamp)); ConcurrentUtils.sleep(2); System.out.println("Optimistic Lock Valid: " + lock.validate(stamp)); } finally { lock.unlock(stamp); } }); executor.submit(() -> { long stamp = lock.writeLock(); try { System.out.println("Write Lock acquired"); ConcurrentUtils.sleep(2); } finally { lock.unlock(stamp); System.out.println("Write done"); } }); ConcurrentUtils.stop(executor); } }
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.StampedLock; public class Lock6 { private static int count = 0; public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(2); StampedLock lock = new StampedLock(); executor.submit(() -> { long stamp = lock.readLock(); try { if (count == 0) { stamp = lock.tryConvertToWriteLock(stamp); if (stamp == 0L) { System.out.println("Could not convert to write lock"); stamp = lock.writeLock(); } count = 23; } System.out.println(count); } finally { lock.unlock(stamp); } }); ConcurrentUtils.stop(executor); } }
import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; public class Lock3 { public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(2); Map<String, String> map = new HashMap<>(); ReadWriteLock lock = new ReentrantReadWriteLock(); executor.submit(() -> { lock.writeLock().lock(); try { ConcurrentUtils.sleep(1); map.put("foo", "bar"); } finally { lock.writeLock().unlock(); } }); Runnable readTask = () -> { lock.readLock().lock(); try { System.out.println(map.get("foo")); ConcurrentUtils.sleep(1); } finally { lock.readLock().unlock(); } }; executor.submit(readTask); executor.submit(readTask); ConcurrentUtils.stop(executor); } }
import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.StampedLock; public class Lock4 { public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(2); Map<String, String> map = new HashMap<>(); StampedLock lock = new StampedLock(); executor.submit(() -> { long stamp = lock.writeLock(); try { ConcurrentUtils.sleep(1); map.put("foo", "bar"); } finally { lock.unlockWrite(stamp); } }); Runnable readTask = () -> { long stamp = lock.readLock(); try { System.out.println(map.get("foo")); ConcurrentUtils.sleep(1); } finally { lock.unlockRead(stamp); } }; executor.submit(readTask); executor.submit(readTask); ConcurrentUtils.stop(executor); } }
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.ReentrantLock; public class Lock2 { public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(2); ReentrantLock lock = new ReentrantLock(); executor.submit(() -> { lock.lock(); try { ConcurrentUtils.sleep(1); } finally { lock.unlock(); } }); executor.submit(() -> { System.out.println("Locked: " + lock.isLocked()); System.out.println("Held by me: " + lock.isHeldByCurrentThread()); boolean locked = lock.tryLock(); System.out.println("Lock acquired: " + locked); }); ConcurrentUtils.stop(executor); } }
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.ReentrantLock; import java.util.stream.IntStream; public class Lock1 { private static final int NUM_INCREMENTS = 10000; private static ReentrantLock lock = new ReentrantLock(); private static int count = 0; private static void increment() { lock.lock(); try { count++; } finally { lock.unlock(); } } public static void main(String[] args) { testLock(); } private static void testLock() { count = 0; ExecutorService executor = Executors.newFixedThreadPool(2); IntStream.range(0, NUM_INCREMENTS) .forEach(i -> executor.submit(Lock1::increment)); ConcurrentUtils.stop(executor); System.out.println(count); } }
import java.security.SecureRandom; import java.util.Arrays; import java.util.stream.IntStream; public class Streams13 { public static void main(String[] args) { SecureRandom secureRandom = new SecureRandom(new byte[]{1, 3, 3, 7}); int[] randoms = IntStream.generate(secureRandom::nextInt) .filter(n -> n > 0) .limit(10) .toArray(); System.out.println(Arrays.toString(randoms)); int[] nums = IntStream.iterate(1, n -> n * 2) .limit(11) .toArray(); System.out.println(Arrays.toString(nums)); } }
import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.UUID; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.TimeUnit; public class Streams12 { public static void main(String[] args) { List<String> strings = Arrays.asList("a1", "a2", "b1", "c2", "c1"); // test1(); // test2(strings); test3(strings); // test4(); } private static void test4() { List<String> values = new ArrayList<>(100); for (int i = 0; i < 100; i++) { UUID uuid = UUID.randomUUID(); values.add(uuid.toString()); } // sequential long t0 = System.nanoTime(); long count = values .parallelStream() .sorted((s1, s2) -> { System.out.format("sort: %s <> %s [%s]\n", s1, s2, Thread.currentThread().getName()); return s1.compareTo(s2); }) .count(); System.out.println(count); long t1 = System.nanoTime(); long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0); System.out.println(String.format("parallel sort took: %d ms", millis)); } private static void test3(List<String> strings) { strings .parallelStream() .filter(s -> { System.out.format("filter: %s [%s]\n", s, Thread.currentThread().getName()); return true; }) .map(s -> { System.out.format("map: %s [%s]\n", s, Thread.currentThread().getName()); return s.toUpperCase(); }) .sorted((s1, s2) -> { System.out.format("sort: %s <> %s [%s]\n", s1, s2, Thread.currentThread().getName()); return s1.compareTo(s2); }) .forEach(s -> System.out.format("forEach: %s [%s]\n", s, Thread.currentThread().getName())); } private static void test2(List<String> strings) { strings .parallelStream() .filter(s -> { System.out.format("filter: %s [%s]\n", s, Thread.currentThread().getName()); return true; }) .map(s -> { System.out.format("map: %s [%s]\n", s, Thread.currentThread().getName()); return s.toUpperCase(); }) .forEach(s -> System.out.format("forEach: %s [%s]\n", s, Thread.currentThread().getName())); } private static void test1() { // -Djava.util.concurrent.ForkJoinPool.common.parallelism=5 ForkJoinPool commonPool = ForkJoinPool.commonPool(); System.out.println(commonPool.getParallelism()); } }
import java.util.Arrays; import java.util.List; public class Streams11 { static class Person { String name; int age; Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return name; } } public static void main(String[] args) { List<Person> persons = Arrays.asList( new Person("Max", 18), new Person("Peter", 23), new Person("Pamela", 23), new Person("David", 12)); // test1(persons); // test2(persons); // test3(persons); // test4(persons); // test5(persons); test6(persons); } private static void test1(List<Person> persons) { persons .stream() .reduce((p1, p2) -> p1.age > p2.age ? p1 : p2) .ifPresent(System.out::println); // Pamela } private static void test2(List<Person> persons) { Person result = persons .stream() .reduce(new Person("", 0), (p1, p2) -> { p1.age += p2.age; p1.name += p2.name; return p1; }); System.out.format("name=%s; age=%s", result.name, result.age); } private static void test3(List<Person> persons) { Integer ageSum = persons .stream() .reduce(0, (sum, p) -> sum += p.age, (sum1, sum2) -> sum1 + sum2); System.out.println(ageSum); } private static void test4(List<Person> persons) { Integer ageSum = persons .stream() .reduce(0, (sum, p) -> { System.out.format("accumulator: sum=%s; person=%s\n", sum, p); return sum += p.age; }, (sum1, sum2) -> { System.out.format("combiner: sum1=%s; sum2=%s\n", sum1, sum2); return sum1 + sum2; }); System.out.println(ageSum); } private static void test5(List<Person> persons) { Integer ageSum = persons .parallelStream() .reduce(0, (sum, p) -> { System.out.format("accumulator: sum=%s; person=%s\n", sum, p); return sum += p.age; }, (sum1, sum2) -> { System.out.format("combiner: sum1=%s; sum2=%s\n", sum1, sum2); return sum1 + sum2; }); System.out.println(ageSum); } private static void test6(List<Person> persons) { Integer ageSum = persons .parallelStream() .reduce(0, (sum, p) -> { System.out.format("accumulator: sum=%s; person=%s; thread=%s\n", sum, p, Thread.currentThread().getName()); return sum += p.age; }, (sum1, sum2) -> { System.out.format("combiner: sum1=%s; sum2=%s; thread=%s\n", sum1, sum2, Thread.currentThread().getName()); return sum1 + sum2; }); System.out.println(ageSum); } }
你可以参考下这个文档:help.aliyun.com/document_detail/oss/api-reference/object/CopyObject.html?spm=5176.7618386.5.1.XyyMQH
请问是ip地址。还是服务器地址。还是其他的什么URL?
动态读取日志配置文件。将其修改即可
户调用MNS HTTP API发送请求时,需要在Authorization header里带上签名值,当签名值和服务器端计算的不一致时,请求会被拒绝,服务器返回403 SignatureDoesNotMatch。
当遇到这种问题,请检查以下几项:
一,请求url是否正确
举ReceiveMessage(curl)为例:
curl -X GET http://44404.mns.cn-beijing.aliyuncs.com/queues/queue1/messages?waitseconds=10 -H "Authorization:MNS ijljkhkhlkjklshiojo................." -H "Date:Mon, 09 Nov 2015 06:24:41 GMT" -H "x-mns-version:2015-06-06"
新协议(x-mns-version:2015-06-06, Authorization:MNS xxxxxxxx...)url为:
http://$AccountID.mns.cn-beijing.aliyuncs.com/queues/$queueName/messages
旧协议(x-mqs-version:2014-07-08, Authorization:MQS xxxxxxxx...)url为:
http://$AccountID.mns.cn-beijing.aliyuncs.com/$queueName/messages
关于新旧协议更多差异,请参考官方API文档:
https://docs.aliyun.com/?spm=5176.7400025.9.11.uXUeIQ#/pub/mns/api_reference/api_spec&message_operation
队列地址中的AccountID即云账户的账号ID。
账号id.jpg
二,AccessKeyId和AccessKeySecrete是否正确
三,加密信息源是否正确
错误一:
GET
n
text/xml;charset=utf-8
Date:Thu, 21 May 2015 03:50:03 GMT
x-mqs-version:2014-07-08
/queue1/messages?waitseconds=10
正确一:
GET
n
text/xml;charset=utf-8
Thu, 21 May 2015 03:50:03 GMT
x-mqs-version:2014-07-08
/queue1/messages?waitseconds=10
错误二:
GET
n
text/xml;charset=utf-8
Thu, 21 May 2015 03:50:03 GMT
x-mns-version:2015-06-06
/queue1/messages?waitseconds=10
正确二:
GET
n
text/xml;charset=utf-8
Thu, 21 May 2015 03:50:03 GMT
x-mns-version:2015-06-06
/queues/queue1/messages?waitseconds=10
错误三:
GET
n
text/xml;charset=utf-8
Thu, 21 May 2015 03:58:23 GMT
n
/queues/queue1/messages?waitseconds=10
正确三:
GET
n
text/xml;charset=utf-8
Thu, 21 May 2015 03:58:23 GMT
/queues/queue1/messages?waitseconds=10
关于Signature计算方法,请参考官方文档:
https://docs.aliyun.com/?spm=5176.7400025.9.11.uXUeIQ#/pub/mns/api_reference/invoke&signature
官网提供了一个demo, 方便用户验证自己的签名过程是否正确,请见问题“为什么我的签名总是没算对?”:
https://docs.aliyun.com/?spm=5176.7400025.9.11.uXUeIQ#/pub/mns/product-manual/FAQ
如果一个请求方法中,包含两次以上操作该对象表,那么在前面每次操作完数据库之后,需要将操作后的对象返回,然后下次操作时,保证该对象的版本号是最新的。
请更新javamail到最新版本。在重试
更新Javamail的jar包到最新版本。在重试一下
1、主要解决针对大型网站架构中持久化部分中,大量数据存储以及高并发访问所带来是数据读写问题。分布式是将一个业务拆分为多个子业务,部署在不同的服务器上。集群是同一个业务,部署在多个服务器上。
2、着重对数据切分做了细致丰富的讲解,从数据切分的原理出发,一步一步深入理解数据的切分,通过深入理解各种切分策略来设计和优化我们的系统。这部分中我们还用到了数据库中间件和客户端组件来进行数据的切分,让广大网友能够对数据的切分从理论到实战都会有一个质的飞跃
调整client.refresh.interval的值更大一些。
NameServer是一个几乎无状态节点,可集群部署,节点之间无任何信息同步。
Broker部署相对复杂,Broker分为Master与Slave,一个Master可以对应多个Slave,但是一个Slave只能对应一个Master,Master与Slave的对应关系通过指定相同的BrokerName,不同的BrokerId来定义,BrokerId为0表示Master,非0表示Slave。Master可以部署多个。每个Broker与Name Server集群中的所有节点建立长连接,定时注册Topic信息到所有NameServer。
Producer与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer取Topic路由信息,并向提供Topic服务的Master建立长连接,且定时向Master发送心跳。Producer完全无状态,可以集群部署。
Consumer与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer取Topic路由信息,并向提供Topic服务的Master、Slave建立长连接,且定时向Master、Slave发送心跳。Consumer既可以从Master订阅消息,也可以从Slave订阅消息,订阅规则由Broker配置决定。
请问您这个是想知道如何实现还是技术架构还是其他的什么呢
有中文的:https://github.com/hankcs/MainPartExtractor 。可以参考一下
线上诊断工具arthas
请问您说的jdk高版本指的是哪个? jdk 8 9 10 11?
请使用阿里线上诊断工具arthas。可以快速定位内存outofmemory问题。
在正常的处理过程中,G1完成了堆的压缩(至少是部分堆的压缩),这样也就不会有cms内存碎片问题的存在了。
是想中途停止还是异常rollback。 如果是异常情况。可以加上 exception rollback;
首先请检查对应目录是否具备读写权限
windows下请 打开属性,属性--->安全---->编辑,然后把除完全控制的其他权限增加上。
在重新运行试试
如自行不能定位内存使用过高问题。推荐使用阿里的arthas。操作可以查阅官网文档。非常简单。几个命令即可查询到对应内存信息。
如可以的话,
1、准备自己的一些博客。
2、或者自己的网站或者其他内容。
3、学习一些相关的技术,熟悉云服务器一些操作。
这样既利用了服务器,而且还可以推广自己。