-
[技术干货] CSEJavaSDK连sc报错 404:Not Found, "error_msg":"API not exist or not published in the environment"某些时候微服务注册到华为云CSE的时候,日志里面会打印错误内容2018-11-05 17:17:04.208 WARN 12692 --- [ntloop-thread-0] o.a.s.s.c.h.ServiceRegistryClientImpl : get response for org.apache.servicecomb.serviceregistry.api.response.GetSchemasResponse failed, 404:Not Found, {"error_msg":"API not exist or not published in the environment","error_code":"APIGW.0101","request_id":"284c5c8b68ceed2411cbe958df208149"}这是由于microservice.yaml文件里面配置的连接服务中心、配置中心等的APIGateway地址还是旧域名https://cse.cn-north-1.myhwclouds.com,改成新的地址https://cse.cn-north-1.myhuaweicloud.com:443 就可以解决问题了。 PS:旧域名的APIGateway已经不更新了,并且预计以后会停止工作。推荐大家根据CSE或ServiceStage的CSE-SDK工具下载页面上发布的地址更新自己的配置
-
retrofit是一个解耦性非常高的网络请求框架,最近在研究的时候发现了动态代理这个非常强大且实用的技术,这篇文章将作为retrofit的前置知识,让大家认识:动态代理有哪些应用场景,什么是动态代理,怎样使用,它的局限性在什么地方?#动态代理的应用场景1. AOP—面向切面编程,程序解耦简言之当你想要对一些类的内部的一些方法,在执行前和执行后做一些共同的的操作,而在方法中执行个性化操作的时候--用动态代理。在业务量庞大的时候能够降低代码量,增强可维护性。2. 想要自定义第三放类库中的某些方法我引用了一个第三方类库,但他的一些方法不满足我的需求,我想自己重写一下那几个方法,或在方法前后加一些特殊的操作--用动态代理。但需要注意的是,这些方法有局限性,我会在稍后说明。什么是动态代理以上的图太过于抽象,我们从生活中的例子开始切入。假如你是一个大房东(被代理人),你有很多套房子想要出租,而你觉得找租客太麻烦,不愿意自己弄,因而你找一个人来代理你(代理人),帮打理这些东西,而这个人(代理人也就是中介)在帮你出租房屋的时候对你收取一些相应的中介费(对房屋出租的一些额外操作)。对于租客而言,中介就是房东,代理你做一些事情。以上,就是一个代理的例子,而他为什么叫动态代理,“动态”两个字体现在什么地方?我们可以这样想,如果你的每一套房子你都请一个代理人帮你打理,每当你想再出租一套房子的时候你得再请一个,这样你会请很多的代理人,花费高额的中介成本,这可以看作常说的“静态代理”。但假如我们把所有的房子都交给一个中介来代理,让他在多套房子之间动态的切换身份,帮你应付每一个租客。这就是一个“动态代理”的过程。动态代理的一大特点就是编译阶段没有代理类在运行时才生成代理类。我们用一段代码来看一下房屋出租的操作/** *定义一个借口 **/public interface RentHouse {void rent();//房屋出租void charge(String str);//出租费用收取}房东public class HouseOwner implements RentHouse {public void rent() { System.out.println("I want to rent my house"); }public void charge(String str) { System.out.println("You get : " + str + " RMB HouseCharge."); } }中介public class DynamicProxy implements InvocationHandler { // 这个就是我们要代理的真实对象,即房东 private Object subject; // 构造方法,给我们要代理的真实对象赋初值 public DynamicProxy(Object subject) { this.subject = subject; } @Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 在代理真实对象前我们可以添加一些自己的操作,中介收取中介费 System.out.println("before "+method.getName()+" house"); System.out.println("Method:" + method.getName()); // 如果方法是 charge 则中介收取100元中介费 if (method.getName().equals("charge")) { method.invoke(subject, args); System.out.println("I will get 100 RMB ProxyCharge."); } else { // 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用 method.invoke(subject, args); } // 在代理真实对象后我们也可以添加一些自己的操作 System.out.println("after "+method.getName()+" house"); return null; }客人public class Client {public static void main(String[] args){ // 我们要代理的真实对象--房东 HouseOwner houseOwner = new HouseOwner(); // 我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的 InvocationHandler handler = new DynamicProxy(houseOwner); /* * 通过Proxy的newProxyInstance方法来创建我们的代理对象,我们来看看其三个参数 * 第一个参数 handler.getClass().getClassLoader() ,我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象 * 第二个参数realSubject.getClass().getInterfaces(),我们这里为代理对象提供的接口是真实对象所实行的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了 * 第三个参数handler, 我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上 */ RentHouse rentHouse = (RentHouse) Proxy.newProxyInstance(handler.getClass().getClassLoader(), houseOwner .getClass().getInterfaces(), handler);//一个动态代理类,中介 System.out.println(rentHouse.getClass().getName()); rentHouse.rent(); rentHouse.charge("10000"); } }我们来看一下输出com.sun.proxy.$Proxy0 before rent house Method:rent I want to rent my house after rent house before charge house Method:charge You get : 10000 RMB HouseCharge. I will get 100 RMB ProxyCharge. after charge house Process finished with exit code 0输出里有 before rent house以及after rent house,说明我们可以在方法的前后增加操作。再看输出 I will get 100 RMB ProxyCharge. 中介收取了100块的中介费,说明我们不仅可以增加操作,甚至可以替换该方法或者直接让该方法不执行。刚开始看代码你可能会有很多疑惑,我们通过以下的内容来看看动态代理应该怎么用。#动态代理该如何使用在java的动态代理机制中,有两个重要的类和接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。每一个动态代理类都必须要实现InvocationHandler这个接口(代码中的中介),并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke(对方法的增强就写在这里面) 方法来进行调用。Object invoke(Object proxy, Method method, Object[] args) throws Throwable我们看到这个方法一共接受三个参数,那么这三个参数分别代表什么呢?Object invoke(Object proxy, Method method, Object[] args) throws Throwable //proxy: 指代我们所代理的那个真实对象 //method: 指代的是我们所要调用真实对象的某个方法的Method对象 //args: 指代的是调用真实对象某个方法时接受的参数接下来我们来看看Proxy这个类public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentExceptionProxy这个类的作用就是用来动态创建一个代理对象的类,它提供了许多的方法,但是我们用的最多的就是 newProxyInstance 这个方法:public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException这个方法的作用就是得到一个动态的代理对象,其接收三个参数,我们来看看这三个参数所代表的含义public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException //loader: 一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载 //interfaces: 一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了 //h: 一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上这样一来,结合上面给出的代码,我们就可以明白动态代理的使用方法了#动态代理的局限性从动态代理的使用方法中我们看到其实可以被增强的方法都是实现了借口的(不实现借口的public方法也可以通过继承被代理类来使用),代码中的HouseOwner继承了RentHouse 。而对于private方法JDK的动态代理无能为力!以上的动态代理是JDK的,对于java工程还有大名鼎鼎的CGLib,但遗憾的是CGLib并不能在android中使用,android虚拟机相对与jvm还是有区别的。结束语动态代理的使用场景远不止这些,内部原理会在以后的文章中介绍,但应用类反射临时生成代理类这一机制决定它对性能会有一定的影响。本文作为retrofit原理的前置文章并没有太过详尽,如有疏漏和错误,欢迎指正!本文转自(51cto 洛基loky)博客51CTO博客,如需转载,请自行联系原作者。原文链接(http://blog.51cto.com/13586365/2065317)
TCDEFGHIJKLMNO1PQRSA
发表于2018-10-30 16:21:53
2018-10-30 16:21:53
最后回复
TCDEFGHIJKLMNO1PQRSA
2018-10-30 16:21:53
4631 0 -
retrofit是一个解耦性非常高的网络请求框架,最近在研究的时候发现了动态代理这个非常强大且实用的技术,这篇文章将作为retrofit的前置知识,让大家认识:动态代理有哪些应用场景,什么是动态代理,怎样使用,它的局限性在什么地方?#动态代理的应用场景1. AOP—面向切面编程,程序解耦简言之当你想要对一些类的内部的一些方法,在执行前和执行后做一些共同的的操作,而在方法中执行个性化操作的时候--用动态代理。在业务量庞大的时候能够降低代码量,增强可维护性。2. 想要自定义第三放类库中的某些方法我引用了一个第三方类库,但他的一些方法不满足我的需求,我想自己重写一下那几个方法,或在方法前后加一些特殊的操作--用动态代理。但需要注意的是,这些方法有局限性,我会在稍后说明。什么是动态代理以上的图太过于抽象,我们从生活中的例子开始切入。假如你是一个大房东(被代理人),你有很多套房子想要出租,而你觉得找租客太麻烦,不愿意自己弄,因而你找一个人来代理你(代理人),帮打理这些东西,而这个人(代理人也就是中介)在帮你出租房屋的时候对你收取一些相应的中介费(对房屋出租的一些额外操作)。对于租客而言,中介就是房东,代理你做一些事情。以上,就是一个代理的例子,而他为什么叫动态代理,“动态”两个字体现在什么地方?我们可以这样想,如果你的每一套房子你都请一个代理人帮你打理,每当你想再出租一套房子的时候你得再请一个,这样你会请很多的代理人,花费高额的中介成本,这可以看作常说的“静态代理”。但假如我们把所有的房子都交给一个中介来代理,让他在多套房子之间动态的切换身份,帮你应付每一个租客。这就是一个“动态代理”的过程。动态代理的一大特点就是编译阶段没有代理类在运行时才生成代理类。我们用一段代码来看一下房屋出租的操作/** *定义一个借口 **/public interface RentHouse {void rent();//房屋出租void charge(String str);//出租费用收取}房东public class HouseOwner implements RentHouse {public void rent() { System.out.println("I want to rent my house"); }public void charge(String str) { System.out.println("You get : " + str + " RMB HouseCharge."); } }中介public class DynamicProxy implements InvocationHandler {// 这个就是我们要代理的真实对象,即房东private Object subject;// 构造方法,给我们要代理的真实对象赋初值public DynamicProxy(Object subject) { this.subject = subject; } @Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 在代理真实对象前我们可以添加一些自己的操作,中介收取中介费 System.out.println("before "+method.getName()+" house"); System.out.println("Method:" + method.getName()); // 如果方法是 charge 则中介收取100元中介费 if (method.getName().equals("charge")) { method.invoke(subject, args); System.out.println("I will get 100 RMB ProxyCharge."); } else { // 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用 method.invoke(subject, args); } // 在代理真实对象后我们也可以添加一些自己的操作 System.out.println("after "+method.getName()+" house"); return null; }客人public class Client {public static void main(String[] args){ // 我们要代理的真实对象--房东 HouseOwner houseOwner = new HouseOwner(); // 我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的 InvocationHandler handler = new DynamicProxy(houseOwner); /* * 通过Proxy的newProxyInstance方法来创建我们的代理对象,我们来看看其三个参数 * 第一个参数 handler.getClass().getClassLoader() ,我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象 * 第二个参数realSubject.getClass().getInterfaces(),我们这里为代理对象提供的接口是真实对象所实行的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了 * 第三个参数handler, 我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上 */ RentHouse rentHouse = (RentHouse) Proxy.newProxyInstance(handler.getClass().getClassLoader(), houseOwner .getClass().getInterfaces(), handler);//一个动态代理类,中介 System.out.println(rentHouse.getClass().getName()); rentHouse.rent(); rentHouse.charge("10000"); } }我们来看一下输出com.sun.proxy.$Proxy0 before rent house Method:rent I want to rent my house after rent house before charge house Method:charge You get : 10000 RMB HouseCharge. I will get 100 RMB ProxyCharge. after charge house Process finished with exit code 0输出里有 before rent house以及after rent house,说明我们可以在方法的前后增加操作。再看输出 I will get 100 RMB ProxyCharge. 中介收取了100块的中介费,说明我们不仅可以增加操作,甚至可以替换该方法或者直接让该方法不执行。刚开始看代码你可能会有很多疑惑,我们通过以下的内容来看看动态代理应该怎么用。#动态代理该如何使用在java的动态代理机制中,有两个重要的类和接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。每一个动态代理类都必须要实现InvocationHandler这个接口(代码中的中介),并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke(对方法的增强就写在这里面) 方法来进行调用。Object invoke(Object proxy, Method method, Object[] args) throws Throwable我们看到这个方法一共接受三个参数,那么这三个参数分别代表什么呢?Object invoke(Object proxy, Method method, Object[] args) throws Throwable//proxy: 指代我们所代理的那个真实对象//method: 指代的是我们所要调用真实对象的某个方法的Method对象//args: 指代的是调用真实对象某个方法时接受的参数接下来我们来看看Proxy这个类public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentExceptionProxy这个类的作用就是用来动态创建一个代理对象的类,它提供了许多的方法,但是我们用的最多的就是 newProxyInstance 这个方法:public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException这个方法的作用就是得到一个动态的代理对象,其接收三个参数,我们来看看这三个参数所代表的含义public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException//loader: 一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载//interfaces: 一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了//h: 一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上这样一来,结合上面给出的代码,我们就可以明白动态代理的使用方法了#动态代理的局限性从动态代理的使用方法中我们看到其实可以被增强的方法都是实现了借口的(不实现借口的public方法也可以通过继承被代理类来使用),代码中的HouseOwner继承了RentHouse 。而对于private方法JDK的动态代理无能为力!以上的动态代理是JDK的,对于java工程还有大名鼎鼎的CGLib,但遗憾的是CGLib并不能在android中使用,android虚拟机相对与jvm还是有区别的。结束语动态代理的使用场景远不止这些,内部原理会在以后的文章中介绍,但应用类反射临时生成代理类这一机制决定它对性能会有一定的影响。本文作为retrofit原理的前置文章并没有太过详尽,如有疏漏和错误,欢迎指正!本文转自洛基loky博客51CTO博客,如需转载,请自行联系原作者。原文链接:http://blog.51cto.com/13586365/2065317
-
实验目的通过使用Java+SDK管理华为云对象存储OBS,了解对象存储的基本原理和操作,熟悉SDK的使用方法,为后续需要开发复杂功能提供入门准备。准备动作1、电脑上安装Java开发环境+Eclipse,可参考网上的教程:Java安装教程:http://www.runoob.com/java/java-environment-setup.html#win-installEclipse+汉化教程:https://blog.csdn.net/weixin_41848531/article/details/817364142、下载华为云OBS SDK,笔者编辑本文时,最小版本是OBS Java SDK 3.0.0 ,SDK安装过程如下:a.下载OBS Java SDK开发包。b. 在Eclipse中创建一个Java工程b. 将解压后的文件:esdk-obs-java-<versionId>.jar 以及third_party文件夹下所有的JAR包拷贝到您的项目中。c. 在Eclipse中选择您的工程,右击选择 Properties > Java Build Path > Add JARs。3、下载OBS的访问密钥key文件。a. 登陆华为云网站(www.huaweicloud.com),进入OBS控制台,下载访问密钥。密钥key是一个xxx.csv的表格文件,其中Access Key Id对应OBS API中的ak,Secret Access Key对应OBS API中的sk。密钥key的作用:通过网站访问对象存储OBS,需要先通过账号密码登陆网站。通过代码访问OBS,如果也需要输入账号密码,就会使得的代码变复杂。因此密钥key可以认为是经过加密的账号和密码,代码中可直接使用。 密钥key文件只在生成的时候提供下载,因此下载后需妥善保存。4、打开JDK包中的开发指南《对象存储Java SDK开发指南.doc》内含丰富的说明。操作步骤 1、在eclipse工程中左侧工具栏中找到自动生成的xxx.java,编写一个java类,输出欢迎语句。点击eclispe工具栏上的 调试或运行按钮,在结果中可看到欢迎语句。package main; import java.io.*;import java.io.IOException; public class main {public static void main(String[] args) {System.out.println("welcome to china!!!");}}2、创建一个OBS客户端。电脑是访问OBS的客户端,华为云的OBS是服务器。2.1 公有云的数据中心是分区域的,每个OBS访问地址都是通过“后缀endpoint”来指定数据是存放在哪个区域的数据中心的。“后缀endpoint”的查询地址:https://developer.huaweicloud.com/endpoint3.3 参考《对象存储服务Java SDK开发指南.doc》分别编辑创建OBS客户端、创建桶、上传对象和查看所有对象,具体代码参考后续完整代码。3.4 点击eclipse的调试或运行按钮,在控制台中显示创建桶成功,显示所有对象成功。控制台中提示日志插件和性能统计错误,不影响功能,可忽略不计。3.5 在华为云OBS 对象存储控制台中,可看到新增生成的桶和上传的文件。完整代码package main; import java.io.*;import java.io.IOException; import com.obs.services.ObsClient;import com.obs.services.exception.Ob**ception;import com.obs.services.model.*; public class main {/* 初始化OBS客户端所需的参数 */private static final String endPoint = "https://your endpoint";private static final String ak = "your ak";private static final String sk = "your sk";private static final String g_bucketName = "hello-obs-demo";private static final String g_bucketLoc = "cn-south-1"; public static void main(String[] args) {System.out.println("welcome to china!!!");/* 创建OBS客户端 */ObsClient obsClient = new ObsClient(ak,sk,endPoint);ObsBucket obsBucket;try {/* 创建一个桶 */obsBucket = createBucket(obsClient);/* 从本地笔记本上传文件到桶里面 */uploadFile(obsClient, obsBucket);/* 列举对象(文件)的信息 */listFile(obsClient,obsBucket);/* 关闭客户端 */}catch (Ob**ception e){System.out.println("main 函数出现错误!!!");}/* 关闭obs客户端 */closeObsClient(obsClient);}/* 创建一个桶 */private static ObsBucket createBucket(ObsClient obsClient) throws Ob**ception{ObsBucket obsBucket = new ObsBucket(g_bucketName,g_bucketLoc); obsClient.createBucket(obsBucket); System.out.println("Create bucket:" + g_bucketName + " successfully!"); return obsBucket;}/* 创建一个对象(文件) */private static void uploadFile(ObsClient obsClient, ObsBucket obsBucket) throws Ob**ception{File newfile = new File("C:\\Users\\xiaoniu\\Desktop\\temp\\hello.txt");obsClient.putObject(obsBucket.getBucketName(), "folder/", newfile);obsClient.putObject(obsBucket.getBucketName(), "hello1", newfile);obsClient.putObject(obsBucket.getBucketName(), "hello2", newfile);}/* 列举对象(文件)的信息 */private static void listFile(ObsClient obsClient, ObsBucket obsBucket) throws Ob**ception{System.out.println("开始测试桶里面的对象信息");ObjectListing objList = obsClient.listObjects(obsBucket.getBucketName());for (ObsObject obj : objList.getObjects()){System.out.println("--:"+obj.getObjectKey()+" (size=" + obj.getMetadata().getContentLength()+")");}}/* 关闭客户端 */private static void closeObsClient(ObsClient obsClient) {try{obsClient.close();}catch (IOException e){System.out.println("close obs client error.");}}}
-
每次都是到这就异常了,已经跑了一晚上了,还是没有下载下来:异常1:异常2:
-
跳槽不算频繁,但参加过不少面试(电话面试、face to face 面试),面过大 / 小公司、互联网 / 传统软件公司,面糊过(眼高手低,缺乏实战经验,挂掉),也面过人,所幸未因失败而气馁,在此过程中不断查缺补漏,养成了踏实、追本溯源、持续改进的习惯,特此将自己经历过、构思过的一些面试题记录下来,如果答案有问题,欢迎拍砖讨论,希望能对找工作或者感兴趣的同学有所帮助,陆续整理中。1. synchronized 和 reentrantlock 异同相同点都实现了多线程同步和内存可见性语义都是可重入锁不同点实现机制不同 synchronized 通过 java 对象头锁标记和 Monitor 对象实现 reentrantlock 通过CAS、ASQ(AbstractQueuedSynchronizer)和 locksupport(用于阻塞和解除阻塞)实现synchronized 依赖 jvm 内存模型保证包含共享变量的多线程内存可见性 reentrantlock 通过 ASQ 的volatile state 保证包含共享变量的多线程内存可见性使用方式不同 synchronized 可以修饰实例方法(锁住实例对象)、静态方法(锁住类对象)、代码块(显示指定锁对象)reentrantlock 显示调用 trylock()/lock() 方法,需要在 finally 块中释放锁功能丰富程度不同 reentrantlock提供有限时间等候锁(设置过期时间)、可中断锁(lockInterruptibly)、condition(提供 await、signal等方法)等丰富语义 reentrantlock 提供公平锁和非公平锁实现 synchronized不可设置等待时间、不可被中断(interrupted)2. concurrenthashmap 为何读不用加锁jdk1.71)HashEntry 中的 key、hash、next 均为 final 型,只能表头**、删除结点2)HashEntry 类的 value 域被声明为 volatile 型3)不允许用 null 作为键和值,当读线程读到某个 HashEntry 的 value 域的值为 null时,便知道产生了冲突——发生了重排序现象(put 设置新 value 对象的字节码指令重排序),需要加锁后重新读入这个 value 值4)volatile 变量 count 协调读写线程之间的内存可见性,写操作后修改 count,读操作先读 count,根据happen-before 传递性原则写操作的修改读操作能够看到jdk1.81)Node 的 val 和 next 均为 volatile 型2)tabAt 和 casTabAt 对应的 unsafe 操作实现了 volatile 语义3. ContextClassLoader(线程上下文类加载器)的作用越过类加载器的双亲委派机制去加载类,如 serviceloader 实现使用线程上下文类加载器加载类,要注意保证多个需要通信的线程间的类加载器应该是同一个,防止因为不同的类加载器导致类型转换异常(ClassCastException)4. tomcat 类加载机制不同应用使用不同的 webapp 类加载器,实现应用隔离的效果,webapp 类加载器下面是 jsp 类加载器不同应用共享的 jar 包可以放到 Shared 类加载器 /shared 目录下5. osgi 类加载机制osgi 类加载模型是网状的,可以在模块(Bundle)间互相委托osgi 实现模块化热部署的关键是自定义类加载器机制的实现,每个 Bundle 都有一个自己的类加载器,当需要更换一个 Bundle时,就把 Bundle 连同类加载器一起换掉以实现代码的热替换当收到类加载请求时,osgi 将按照下面的顺序进行类搜索:1)将以 java.* 开头的类委派给父类加载器加载2)否则,将委派列表名单(配置文件 org.osgi.framework.bootdelegation 中定义)内的类委派给父类加载器加载3)否则,检查是否在 Import-Package 中声明,如果是,则委派给 Export 这个类的 Bundle 的类加载器加载4)否则,检查是否在 Require-Bundle 中声明,如果是,则将类加载请求委托给 required bundle 的类加载器5)否则,查找当前 Bundle 的 ClassPath,使用自己的类加载器加载6)否则,查找类是否在自己的 Fragment Bundle 中,如果在,则委派给 Fragment Bundle 的类加载器加载7)否则,查找 Dynamic Import-Package(Dynamic Import 只有在真正用到此 Package的时候才进行加载)的 Bundle,委派给对应 Bundle 的类加载器加载8)否则,类查找失败6. 如何结束一个一直运行的线程使用退出标志,这个 flag 变量要多线程可见使用 interrupt,结合 isInterrupted() 使用7. threadlocal 使用场景及问题threadlocal 并不能解决多线程共享变量的问题,同一个 threadlocal 所包含的对象,在不同的 thread中有不同的副本,互不干扰用于存放线程上下文变量,方便同一线程对变量的前后多次读取,如事务、数据库 connection 连接,在 web 编程中使用的更多问题: 注意线程池场景使用 threadlocal,因为实际变量值存放在了 thread 的 threadlocalmap类型变量中,如果该值没有 remove,也没有先 set 的话,可能会得到以前的旧值问题: 注意线程池场景下的内存泄露,虽然 threadlocal 的 get/set 会清除 key(key 为 threadlocal的弱引用,value 是强引用,导致 value 不释放)为 null 的 entry,但是最好 remove8. 线程池从启动到工作的流程刚创建时,里面没有线程调用 execute() 添加任务时:1)如果正在运行的线程数量小于核心参数 corePoolSize,继续创建线程运行这个任务2)否则,如果正在运行的线程数量大于或等于 corePoolSize,将任务加入到阻塞队列中3)否则,如果队列已满,同时正在运行的线程数量小于核心参数 maximumPoolSize,继续创建线程运行这个任务4)否则,如果队列已满,同时正在运行的线程数量大于或等于 maximumPoolSize,根据设置的拒绝策略处理5)完成一个任务,继续取下一个任务处理6)没有任务继续处理,线程被中断或者线程池被关闭时,线程退出执行,如果线程池被关闭,线程结束7)否则,判断线程池正在运行的线程数量是否大于核心线程数,如果是,线程结束,否则线程阻塞。因此线程池任务全部执行完成后,继续留存的线程池大小为corePoolSize8)本文所列出的 14 个 Java面试题只是我所遭遇的面试中的一部分,其他的面试题我也会陆续整理出来,说到这里另外顺便给大家推荐一个架构交流学习群:650385180,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty 源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,相信对于已经工作和遇到技术瓶颈的码友,在这个群里会有你需要的内容。9. 阻塞队列 BlockingQueue take 和 poll 区别poll(time):取走 BlockingQueue 里排在首位的对象, 若不能立即取出,则可以等 time参数规定的时间,取不到时返回 nulltake():取走 BlockingQueue 里排在首位的对象,若 BlockingQueue 为空,阻塞直到BlockingQueue 有新的对象被加入10. 如何从 FutureTask 不阻塞获取结果get(long timeout,TimeUnit unit),超时则返回轮询,先通过 isDone()判断是否结束,然后调用 get()11. blockingqueue 如果存放了比较关键的数据,系统宕机该如何处理开放性问题,欢迎讨论将队列持久化,比较麻烦,需要将生产数据持久化到磁盘,持久化成功才返回,消费者线程从磁盘加载数据到内存阻塞队列中,维护消费offset,启动时,根据消费 offset 从磁盘加载数据加入消息队列,保证消息不丢失,生成序列号,消费幂等,根据消费进程决定系统重启后的生产状态12. NIO 与传统 I/O 的区别节约线程,NIO 由原来的每个线程都需要阻塞读写变成了由单线程(即 Selector)负责处理多个 channel注册(register)的兴趣事件(SelectionKey)集合(底层借助操作系统提供的 epoll()),netty bossgroup 处理 accept 连接(没看明白为什么 bossgroup 设置多个 thread的必要性),workergroup 处理具体业务流程和数据读写NIO 提供非阻塞操作传统 I/O 以流的方式处理数据,而 NIO 以块的方式处理数据,NIO 提供 bytebuffer,分为堆内和堆外缓冲区,读写时均先放到该缓冲区中,然后由内核通过 channel传输到对端,堆外缓冲区不走内核,提升了性能13. list 中存放可重复字符串,如何删除某个字符串调用 iterator 相关方法删除倒删,防止正序删除导致的数组重排,index 跳过数组元素问题14. 有哪些 GC ROOTS(跟日常开发比较相关的是和此相关的内存泄露)所有 Java 线程当前活跃的栈帧里指向 GC 堆里的对象的引用,因此用不到的对象及时置 null,提升内存回收效率静态变量引用的对象,因此减少静态变量特别是静态集合变量的大小,集合存放的对象覆写 euqls()和 hashcode(),防止持续增长本地方法 JNI 引用的对象方法区中的常量引用的对象,因此减少在长字符串上调用 String.intern()classloader 加载的 class 对象,因此自定义 classloader 无效时及时置 null并且注意类加载器加载对象之间的隔离jvm 里的一些静态数据结构里指向 GC 堆里的对象的引用…本文转自茶轴的青春博客51CTO博客,如需转载,请自行联系原作者。原文链接
-
-容器教科书-系列第一讲:【容器教科书】创刊首航! 3个月前,一篇名为《你的同龄人正在抛弃你》的文章火遍了大街小巷,互联网的每一个角落都呼唤着那个传奇——同龄人。 同龄人是谁,我们已经不得而知了。为了不被他们再一次抛弃,小编作为一个有良知、有自信、有责任心的良好青年,决定用自己潜心修炼的结果帮助大家! 俗话说360行,行行出状元。如今,各行各业别说状元,探花都挤满了人。怎么办?急,在线等。经过长期在技术领域的蛰伏,我终于发现了点儿什么!真相就是——容器技术! 时下,容器技术火到没朋友,Docker、K8s的发展速度让人瞠目结舌!赞叹之余,就不能想想从中可以获得些啥机会吗? 嘿嘿,这个世界总是在默默的奖励那些不断学习的人。小编看各位朋友骨骼惊奇,一看就知道是学习容器技术的练武奇才,维护互联网正义与和平的任务就交给你们了好不好?学习三步走!海陆空360度全方位贴身辅助!1第一步:容器教科书·删繁就简,手把手让你成为容器大师!华为云容器大咖潜心钻研,终于制定出详尽的“容器大师速成秘笈”,PPT手把手教学!容器技术轻松Get,妈妈再也不用担心我的学习!学习也能美滋滋。2第二步:随堂练习·好记性不如烂笔头!高考级针对性的命题帮助你海陆空360度全方位无死角的掌握容器知识。俗话说,好记性不如烂笔头,多做练习,成为容器大师不再是梦想!老师经常说我们,一看就懂,一学就会,一做就错。我们要勇敢Say NO!没有练习可还行?配合容器教科书的学习资料,我们推出了非常优秀的随堂练习!保证海陆空360度全方位无死角的打击知识盲点,堪称高考命题级呢!3第三步:兴趣宝典·大咖直播秀,容器技术新鲜干货抢先尝! 通过Cloud Native Lives系列直播将带你走进云原生技术的核心,深入浅出的为您讲解云原生技术的方方面面:容器化、微服务、动态管理。结合CNCF(Cloud Native Computing Foundation)社区的成功项目,为您剖析它们的原理及核心技术架构,并在课程中进行实践操作,帮助您快速理解掌握云原生的内涵。 讲师团队主要由华为云容器服务团队的核心架构师组成,包括多名CNCF社区的maintainer、committer,负责、参与了多个CNCF社区项目的设计和开发,将带给您最原汁原味云原生讲解。 系列直播传送门:https://bbs.huaweicloud.com/forum/thread-9573-1-1.html 关注【容器教科书】系列资讯,定期完成随堂实践,时刻关注大咖精彩直播,假以时日,相信您一定可以成为容器领域的专家! 最后,文末附上首期《Docker培训教材》PPT以及随堂实践作业一份,感兴趣的朋友可以尝鲜了解啦~Docker培训教材.pdf( 预览 )课程一课后实践.pdf( 预览 )
-
前几天老姐突然告诉我,她在JD上买了本电子图书,然后买完发现,只能在线或者使用它自己的阅读器看,很不方便,让我给想想办法。 然后我就开始琢磨,最开始,我直接使用Acrobat Reader打开,发现只有目录,没有其他,而且页面上面的都存在,我想可能在真正的内容上增加了一块蒙版,只能有"钥匙"的人可以过滤它,要破解别人的编辑器,短时间肯定是不行的,网上也有很多人想到使用自动化脚本去自动对官方阅读器截图,但是我发现,截图不是一页一页的,这就很懵逼了。最后只能通过在线阅读这条线来想办法。 这个办法和网友的类似,都是保存为图片,然后通过pdf工具制作成pdf。 在线阅读我惊奇发现,在线文档真好,一页一张图片,它已经给你做好,只是每次只更新出当前页的前后几张,其他的会被清除。到这里,思路就有了: [*]跳转到第n页[*]拉取刷新出来的额图片路径[*]保存图片路径到缓存(我使用的是redis)[*]通过网络工具类,将缓存中的图片地址全部下载到本地本次为图片[*]将图片通过pdf工作转为pdf 第1步到第3步需要重复,可以使用自动工具和脚本来实现。 第4步写个控制器就可以了,最简单的java接口就行。 第5步直接网上在线服务就可以实现。 为什么需要先缓存在下载咧,这里涉及到一个效率与图片去重和过滤的问题,因为每次调整后获取的图片可能有重复的,存在redis的map中,自动就去重了;也是为了避免一边获取图片路径,一边下载中途异常退出等任务不能正常执行完毕等问题。然后脚本获取路径,后保存到自己的服务器,唯一的问题可能就是跨域的问题。结果发现还是少了几张图,这样就体会出使用缓存的好处了,可以直接通过代码验证少了那几张图,不用去检查jpg文件,少的文件个位数,最后通过手动补全了。 通过这种方式得到的图片,唯一缺陷就是带有"JD读书"字样和图片分辨率不是很高,字体好像带点毛脚。有强迫症或者追求高品质的,就使用官方阅读器吧,个人看了蛮清晰的,是文档,不是图片!!! 下面附上java通过URL获取网络数据保存到本地的代码。18851 调用: 18852此方法只适应已经购买了的电子书,未购买的不适用。建议还是到正规网站或书店购买,支持正版,尊重知识。 [hr]本文转自狐狈筱筱生博客51CTO博客,如需转载,请自行联系原作者。原文链接
-
[color=rgb(255,255,255)]编辑词条 【问题现象】 使用OBS Java SDK在Linux机器上使用“obs.myhwclouds.com”域名调用上传对象接口,报错"UnknowHostException"。 【分析过程】1.在运行环境上可正常ping通obs.myhwclouds.com,并且使用dig命令也能正常解析obs.myhwclouds.com,排除网络原因。 2.分析OBS Java SDK,所用的HttpClient框架底层是通过JDK标准库进行域名解析的,该标准库不会存在BUG,因此怀疑是运行环境的问题。 3.查询JDK标准库域名解析算法的相关资料,发现JDK标准库会读取运行环境上的/etc/resolv.conf文件,以获取DNS配置从而解析出IP,如果JVM进程对该文件没有读权限,可能导致"UnknowHostException"异常。 4.排查运行环境发现运行JVM进程的用户确实没有读/etc/resolv.conf文件的权限,修改权限后,问题解决。 【经验总结】报错的表象和根因看起来差得比较远,要深入问题本质才能分析出来。
-
现象描述运行MapReduce任务时出现如下错误:java.io.IOException: java.io.IOException: Could not find Job details for JobId:job_1417092389329_0004 in JobHistoryServer. at org.apache.hadoop.mapreduce.v2.hs.HistoryClientService$HSClientProtocolHandler.verifyAndGetJob(HistoryClientService.java:216) at org.apache.hadoop.mapreduce.v2.hs.HistoryClientService$HSClientProtocolHandler.getTaskAttemptCompletionEvents(HistoryClientService.java:277) at org.apache.hadoop.mapreduce.v2.api.impl.pb.service.MRClientProtocolPBServiceImpl.getTaskAttemptCompletionEvents(MRClientProtocolPBServiceImpl.java:173) at org.apache.hadoop.yarn.proto.MRClientProtocol$MRClientProtocolService$2.callBlockingMethod(MRClientProtocol.java:283) at org.apache.hadoop.ipc.ProtobufRpcEngine$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine.java:585) at org.apache.hadoop.ipc.RPC$Server.call(RPC.java:928) at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:2013) at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:2009) at java.security.AccessController.doPrivileged(Native Method) at javax.security.auth.Subject.doAs(Subject.java:415) at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1612) at org.apache.hadoop.ipc.Server$Handler.run(Server.java:2007) 可能原因在运行MapReduce任务时,如果HDFS出现故障后恢复,则会出现此错误。 定位思路请检查运行的任务是否运行完成,如果任务已完成,表示该错误是因为HDFS服务出现故障后恢复之后引入的。不需要执行更多的操作。如果任务未完成,请检查MapReduce任务的应用程序。 处理步骤无。
-
下载地址:http://redis.googlecode.com/files/redis-2.0.4.tar.gz 2.0 目前是最新稳定版可以在linux下运行如下命令进行安装 15083 make完后redis-2.0.4目录下会出现编译后的redis服务程序redis-server,还有用于测试的客户端程序redis-cli 启动redis服务: 1.默认方式启动命令: $./redis-server 注意这种方式启动redis 使用的是默认配置。也可以通过启动参数告诉redis使用指定配置文件使用下面命令启动. 2.配置文件方式启动命令: $ ./redis-server redis.conf redis.conf是一个默认的配置文件。我们可以根据需要使用自己的配置文件。启动redis服务进程后,就可以使用测试客户端程序redis-cli和redis服务交互了. 如: 15084 3.java客户端配置: 客户端jar包地址 http://cloud.github.com/downloads/alphazero/jredis/jredis-1.0-rc2.jar 下载后引入jar包到工程,maven项目可以将jar包添加到本地仓库,将jar包添加到maven仓库的命令可自行百度,添加完后在pom文件中引入依赖即可。 java代码示例: package jredisStudy; import org.jredis.*; import org.jredis.ri.alphazero.JRedisClient; public class RedisTest { public static void main(String[] args) { try { JRedis jr = new JRedisClient("192.168.56.55",6379); //redis服务地址和端口号 String key = "mKey"; jr.set(key, "hello,redis!"); String v = new String(jr.get(key)); String k2 = "count"; jr.incr(k2); jr.incr(k2); System.out.println(v); System.out.println(new String(jr.get(k2))); } catch (Exception e) { // TODO: handle exception } } }
-
有没有go服务调用java服务的DEMO
-
索引的作用:当一个集合数据量很大时,从这个集合中查找某条记录时,会从这个集合的第一条顺序查找起直到找到特定记录或者查找完整个集合,这个查找时间会很长,查询花费的时间几十秒到几分钟。而索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,当查找特定记录时就从这个特殊的易于遍历的数据结构中查找,查询花费的时间大大的缩短。 创建索引:MongoDB使用 createIndex () 方法来创建索引,具体命令:db.collection. createIndex ({key:1}),其中collection为要在集合上创建索引的集合名, Key 值为你要创建的索引字段,1为指定按升序创建索引,-1为指定按降序创建索引。 索引分类: 单字段索引: 只在一个字段上建立索引,db.collection. createIndex ({key:1}),这样就在集合collection上的字段key创建了升序的单字段索引。建立了单字段索引后,就能加速对key字段的查询速度。Mongodb对每个集合默认建立的_id字段就是一个单字段索引,也是唯一的主键。复合索引: db.collection.createIndex({key:1,key1:1})建立在两个字段key,key1上的复合索引,所谓复合索引就是针对多个字段联合创建的索引,先按第一个字段排序,第一个字段相同的文档按第二个字段排序,依次类推。复合索引不仅能满足多个字段组合起来的查询,也能满足所以能匹配符合索引前缀的查询。例如db.collection.createIndex({key:1,key1:1})不仅能在字段key,key1上加速查询,也能满足只查找key字段的加速查询。但如果只查找key1字段,则无法进行索引加速。如果经常在key1字段上查询,则应该建立db.collection. createIndex ({key1:1,key:1})的符合索引。除了查询的需求能够影响索引的顺序,字段的值分布也是一个重要的因素。如果 key字段的取值很有限,即拥有相同key字段的文档会有很多;而key1字段的取值则丰富很多,拥有相同key1字段的文档很少,则先按key1字段查找,再在相同key1的文档里查找key字段更为高效。hash索引:db.collection.createIndex({key: "hashed"})这样就在字段key上创建了hash索引,mongodb自动计算字段的hash值,无需用户计算,hash索引只能进行字段的完全匹配查询,不能进行范围查询。 索引的一些特殊属性:唯一索引:对于某些字段值,用户希望是唯一的不重复的,这时就可以设置索引的属性为唯一的。db.collection.createIndex({key: 1 },{ unique: true })在创建key字段为索引的时候加上属性字段unique建立的就是唯一单字段索引。db.collection.createIndex({key: 1, key1: 1 },{ unique: true })创建的就是唯一复合索引。TTL索引: 如果希望当某些记录超过一段时间后,自动从数据库里面被删除,那就可以在建立索引的时候带上TTL属性,但需要满足一个条件:建立TTL索引的那个字段必须是data类型的字段或者包含data类型的数组。db. collection.createIndex({"lastModifiedDate": 1 }, { expireAfterSeconds: 3600 }),其中lastModifiedDate字段的类型必须是data或包含data的数组,这样当lastModifiedDate字段的值距离当前时间值超过3600秒后就会被删除。 索引优化: 当一个建立索引的查询依然花费较长时间时,怎么看这个索引存在的问题呢?可以通过查询计划来决定如何优化。在查找语句后面加上.explain()例如: db.collection.find({key:18}).explain(),通过查询的执行计划可以看出索引上是否存在问题:查询的字段没有建立索引,建立了索引但执行查询时没有使用预期的索引。
-
人工智能技术的提升不仅为企业的运营带来了效率,而且为人民的生活带来了便利。迄今为止,人工智能已经实现了生物识别智能、自动驾驶汽车和人脸识别等等项目。 就像大多数软件应用程序的开发一样,开发人员也在使用多种语言来编写人工智能项目,但是现在还没有任何一种完美的编程语言是可以完全速配人工智能项目的。编程语言的选择往往取决于对人工智能应用程序的期望功能。关于最佳人工智能编程语言的争论从未停止,所以本文就来比较5种人工智能项目最常用的编程语言,并列出它们的优缺点。 Python 由于其语法,简单性和多功能性,Python成为开发人员最喜欢的人工智能开发编程语言。Python最打动人心的地方之一就是便携性,它可以在Linux、Windows、Mac OS和UNIX等平台上使用。允许用户创建交互式的、解释的、模块化的、动态的、可移植的和高级的代码。 另外,Python是一种多范式编程语言,支持面向对象,过程式和功能式编程风格。由于其简单的函数库和理想的结构,Python支持神经网络和NLP解决方案的开发。 优点 Python有丰富多样的库和工具。 支持算法测试,而无需实现它们。 Python的面向对象设计提高了程序员的生产力。 与Java和C ++相比,Python的开发速度更快。 缺点 习惯使用Python来编写人工智能程序的程序员很难适应其它语言的语法。 与c++和Java不同的是,Python需要在解释器的帮助下工作,这就会拖慢在AI开发中的编译和执行速度。 不适合移动计算。 C ++ 优点 c++是最快的计算机语言,如果你的人工智能项目对于时间特别敏感,那么C++是很好的选择,它提供更快的执行时间和更快的响应时间(这也是为什么它经常应用于搜索引擎和游戏)。此外,c++允许广泛使用算法,并且在使用统计人工智能技术方面是有效的。另一个重要的因素是c++支持在开发中重用代码。 C ++适用于机器学习和神经网络。 缺点 多任务处理不佳; C ++仅适用于实现特定系统或算法的核心或基础。 它遵循自下而上的方法,因此非常复杂。 Java Java也是一种多范式语言,遵循面向对象的原则和一次写入读取/随处运行(WORA)的原则。它是一种AI编程语言,可以在任何支持它的平台上运行,而无需重新编译。 在各种项目的开发中,Java都是常用语言之一,它不仅适用于NLP和搜索算法,还适用于神经网络。 Lisp 优点 Lisp是一门计算机编程语言,是继Fortran之后的第二古老的编程语言。随着时间的推移,LISP逐渐发展成为一种强大的、动态的编码语言。 有人认为Lisp是最好的人工智能编程语言,因为它为开发人员提供了自由。在人工智能中使用Lisp,因其灵活性可以快速进行原型设计和实验,当然这也反过来促进Lisp在AI开发中的发展,例如,Lisp有一个独特的宏系统,有助于开发和实现不同级别的智能。 与大多数人工智能编程语言不同,Lisp在解决特定问题时更加高效,因为它适应了开发人员编写解决方案的需求,非常适合于归纳逻辑项目和机器学习。 缺点 很少有开发人员熟悉Lisp编程。 作为一种较古老的编程语言,Lisp需要配置新的软件和硬件来适应它的使用。 Prolog Prolog也是古老的编程语言之一,与Lisp一样,它也是人工智能项目开发的常用语言,拥有灵活框架的机制,它是一种基于规则和声明性的语言,包含了决定其人工智能编码语言的事实和规则。 Prolog支持基本的机制,例如模式匹配、基于树的数据结构和人工智能编程的自动回溯。除了在人工智能项目中广泛使用外,Prolog还用于创建医疗系统。 本文转自:IT168网站
上滑加载中
推荐直播
-
华为云码道Agent集成与鸿蒙实战2026/08/11 周二 19:00-21:00
王一男-华为云码道产品规划专家;李炎-华为云码道产品专家;彭江敏-华为云鸿蒙端云一体化开发专家
本次直播带你解读华为云码道7月份产品新特性、新功能。更有专家演示码道Agent Space × 钉钉机器集成实战,从0到1打通消息通道;码道鸿蒙端云一体化实战,快速搭建员工签到系统。
回顾中 -
华为云开发者AI素养直播课·第五期2026/09/04 周五 16:00-18:00
林华鼎-华为云AI开发者运营负责人;蒋春阳-华为云AI开发者案例开发专家
本期直播内容: AI工具体验营 · 第5-8课连讲。Agent-Team 多智能体协作完成毕业设计实践
回顾中 -
华为云开发者AI素养ClassRoom·第六期2026/09/08 周二 19:00-20:00
樊渊-2026华为软件挑战赛冠军
高手来了:看软挑高手解析二维排样问题—从工业难题到算法突破
回顾中
热门标签