CNI

CNI 常见的 CNI 插件包括 Calico、flannel、Terway、Weave Net 以及 Contiv。 在对CNI插件们进行比较之前,我们可以先对网络中会见到的相关术语做一个整体的了解。不论是阅读本文,还是今后接触到其他和CNI有关的内容,了解一些常见术语总是非常有用的。 一些最常见的术语包括: 第2层网络: OSI (Open Systems Interconnections,开放系统互连)网络模型的“数据链路”层。第2层网络会处理网络上两个相邻节点之间的帧传递。第2层网络的一个值得注意的示例是以太网,其中MAC表示为子层。 第3层网络: OSI网络模型的“网络”层。第3层网络的主要关注点,是在第2层连接之上的主机之间路由数据包。IPv4、IPv6和ICMP是第3层网络协议的示例。 VXLAN:代表“虚拟可扩展LAN”。首先,VXLAN用于通过在UDP数据报中封装第2层以太网帧来帮助实现大型云部署。VXLAN虚拟化与VLAN类似,但提供更大的灵活性和功能 (VLAN仅限于4096个网络ID)。VXLAN是一种封装和覆盖协议,可在现有网络上运行。 Overlay网络:Overlay网络是建立在现有网络之上的虚拟逻辑网络。Overlay网络通常用于在现有网络之上提供有用的抽象,并分离和保护不同的逻辑网络。 封装:封装是指在附加层中封装网络数据包以提供其他上下文和信息的过程。在overlay网络中,封装被用于从虚拟网络转换到底层地址空间,从而能路由到不同的位置 (数据包可以被解封装,并继续到其目的地)。 网状网络:网状网络 (Mesh network)是指每个节点连接到许多其他节点以协作路由、并实现更大连接的网络。网状网络允许通过多个路径进行路由,从而提供更可靠的网络。网状网格的缺点是每个附加节点都会增加大量开销。 BGP:代表“边界网关协议”,用于管理边缘路由器之间数据包的路由方式。BGP通过考虑可用路径,路由规则和特定网络策略,帮助弄清楚如何将数据包从一个网络发送到另一个网络。BGP有时被用作CNI插件中的路由机制,而不是封装的覆盖网络。 CNI比较 Flannel 链接:https://github.com/coreos/fla… 由CoreOS开发的项目Flannel,可能是最直接和最受欢迎的CNI插件。它是容器编排系统中最成熟的网络结构示例之一,旨在实现更好的容器间和主机间网络。随着CNI概念的兴起,Flannel CNI插件算是早期的入门。 与其他方案相比,Flannel相对容易安装和配置。它被打包为单个二进制文件flanneld,许多常见的Kubernetes集群部署工具和许多Kubernetes发行版都可以默认安装 Flannel. Flannel可以使用Kubernetes集群的现有etcd集群来使用API存储其状态信息,因此不需要专用的数据存储。 Flannel配置第3层IPv4 overlay网络。它会创建一个大型内部网络,跨越集群中每个节点。在此overlay网络中,每个节点都有一个子网,用于在内部分配IP地址。在配置pod时,每个节点上的Docker桥接口都会为每个新容器分配一个地址。同一主机中的Pod可以使用Docker桥接进行通信,而不同主机上的pod会使用flanneld将其流量封装在UDP数据包中,以便路由到适当的目标。 Flannel有几种不同类型的后端可用于封装和路由。默认和推荐的方法是使用VXLAN,因为VXLAN性能更良好并且需要的手动干预更少。 总的来说,Flannel是大多数用户的不错选择。从管理角度来看,它提供了一个简单的网络模型,用户只需要一些基础知识,就可以设置适合大多数用例的环境。一般来说,在初期使用Flannel是一个稳妥安全的选择,直到你开始需要一些它无法提供的东西。 Calico 链接:https://github.com/projectcal… Calico是Kubernetes生态系统中另一种流行的网络选择。虽然Flannel被公认为是最简单的选择,但Calico以其性能、灵活性而闻名。Calico的功能更为全面,不仅提供主机和pod之间的网络连接,还涉及网络安全和管理。Calico CNI插件在CNI框架内封装了Calico的功能。 在满足系统要求的新配置的Kubernetes集群上,用户可以通过应用单个manifest文件快速部署Calico。如果您对Calico的可选网络策略功能感兴趣,可以向集群应用其他manifest,来启用这些功能。 尽管部署Calico所需的操作看起来相当简单,但它创建的网络环境同时具有简单和复杂的属性。与Flannel不同,Calico不使用overlay网络。相反,Calico配置第3层网络,该网络使用BGP路由协议在主机之间路由数据包。这意味着在主机之间移动时,不需要将数据包包装在额外的封装层中。BGP路由机制可以本地引导数据包,而无需额外在流量层中打包流量。 除了性能优势之外,在出现网络问题时,用户还可以用更常规的方法进行故障排除。虽然使用VXLAN等技术进行封装也是一个不错的解决方案,但该过程处理数据包的方式同场难以追踪。使用Calico,标准调试工具可以访问与简单环境中相同的信息,从而使更多开发人员和管理员更容易理解行为。 除了网络连接外,Calico还以其先进的网络功能而闻名。 网络策略是其最受追捧的功能之一。此外,Calico还可以与服务网格Istio集成,以便在服务网格层和网络基础架构层中解释和实施集群内工作负载的策略。这意味着用户可以配置强大的规则,描述pod应如何发送和接受流量,提高安全性并控制网络环境。 如果对你的环境而言,支持网络策略是非常重要的一点,而且你对其他性能和功能也有需求,那么Calico会是一个理想的选择。此外,如果您现在或未来有可能希望得到技术支持,那么Calico是提供商业支持的。一般来说,当您希望能够长期控制网络,而不是仅仅配置一次并忘记它时,Calico是一个很好的选择。

2012-09-26 · 1 min · 48 words · -

Java

Java Java,是由_Sun Microsystems_公司于1995年5月推出的Java程序设计语言和Java平台的总称。用Java实现的HotJava浏览器 (支持Java applet) 显示了Java的魅力: 跨平台、动态的Web、Internet计算。从此,Java被广泛接受并推动了Web的迅速发展,常用的浏览器现在均支持Java applet。 1995年5月23日,Java语言诞生 1996年1月,第一个JDK-JDK1.0诞生 1996年4月,10个最主要的操作系统供应商申明将在其产品中嵌入JAVA技术 1996年9月,约8.3万个网页应用了JAVA技术来制作 1997年2月18日,JDK1.1发布 1997年4月2日,JavaOne会议召开,参与者逾一万人,创当时全球同类会议规模之纪录 1997年9月,JavaDeveloperConnection社区成员超过十万 1998年2月,JDK1.1被下载超过2,000,000次 1998年12月8日,JAVA2企业平台J2EE发布 1999年6月,SUN公司发布Java的三个版本: 标准版 (J2SE) 、企业版 (J2EE) 和微型版 (J2ME) 2000年5月8日,JDK1.3发布 2000年5月29日,JDK1.4发布 2001年6月5日,NOKIA宣布,到2003年将出售1亿部支持Java的手机 2001年9月24日,J2EE1.3发布 2002年2月26日,J2SE1.4发布,自此Java的计算能力有了大幅提升 2004年9月30日18:00PM,J2SE1.5发布,成为Java语言发展史上的又一里程碑。为了表示该版本的重要性,J2SE1.5更名为Java SE 5.0 2005年6月,JavaOne大会召开,SUN公司公开Java SE 6。此时,Java的各种版本已经更名,以取消其中的数字"2": J2EE更名为Java EE,J2SE更名为Java SE,J2ME更名为Java ME 2006年12月,SUN公司发布JRE6.0 2009年12月,SUN公司发布Java EE 6 2010年11月,由于Oracle公司对于Java社区的不友善,因此Apache扬言将退出JCP[7] 2011年7月28日,Oracle公司发布Java SE 7 一、算术运算符: 单目: + (取正) - (取负) ++ (自增1) - - (自减1) 双目: + - * / % (取余) 三目: a>b?true:false 说明: 当a大于b的时候,为true (也就是冒号之前的值) ,否则为false;这整个运算符包括一个关系运算符 (可以是">""<""!=“等等) ,一个”?",一个": “,冒号前后需要有两个表达式或者是值或者是对象。 ...

2012-09-26 · 1 min · 189 words · -

Java 数据对象 JDO,JDBC

Java 数据对象 JDO,JDBC http://developer.51cto.com/art/200510/6932.htm 介绍 Java 数据对象 (JDO) is 是一个存储Java对象的规范. 它已经被JCP组织定义成JSR12规范。JDO的第一个版本在2000年6月6日提交并在2002年4月30日正式发布1.0版本规范。规范的两个主要目的是提供数据处理和访问机制的API以及允许规范的实现作为应用服务器的一部分。 JDO 和 JDBC JDBC和JDO都是Java调用数据库的APIs。区别在于,他们访问数据存储的具体方法不同。JDBC提供了一种非常好的机制,它可以使应用程序代码与具体的数据库厂商和数据库位置无关。在大多数情况下数据存储使用的是关系数据库。但是当使用JDBC驱动运行在一个非关系数据库时就不是很好了。而对于JDO来说,运行在它之下的数据库就可以是一个关系数据库,面向对象的数据库或者其他完全不同的数据库。在JDO运行于关系数据库之上时,它可以通过JDBC很好的完成数据存储。而这一切对于开发人员来说都是透明的,所有实现都有JDO本身来完成。 JDBC不支持面向对象的数据库表示。JDBC数据库表示完全围绕关系数据库模型。这常常导致书写代码时在应用程序和数据库之间存在一个中间层。这个层的作用也许是分解Java对象。分解Java对象的过程会对使用的对象稍作改变,这样对象才能存储到关系数据库之中。同样的必须存在一种机制来把数据库中的记录转换成适当的Java对象。JDO与JDBC刚好相反,他的数据库标示完全面向对象。这种机制并不新奇,在一些面向对象数据库中已经使用了这种机制。 JDBC的查询语言一般都是用SQL。JDO的查询语言看起来与Java更接近。使用JDO无需再专门学习一种查询语言比如SQL。如果你会用Java那么你就能够使用JDO的查询语言。 执行 JDO规范定义了JDO实现的接口已经JDO实现的内容。SUN提供了一个JDO规范的参考实现,但是在2002年5月份发布的版本中它并没有完全实现规范中所要求的内容。还有众多的厂商提供的JDO实现可以使用。在下面的表格中列出了一部分。 厂商 产品 SolarMetric Kodo JDO PrismTech OpenFusion Java Data Objects Signsoft intelliBO Poet FastObjects API

2012-09-25 · 1 min · 34 words · -

Collection List Set Map 区别

Collection List Set Map 区别 这些都代表了Java中的集合,这里主要从其元素是否有序,是否可重复来进行区别记忆,以便恰当地使用,当然还存在同步方面的差异,见上一篇相关文章。 有序否 允许元素重复否 Collection 否 是 List 是 是 Set 是 是 HashSet TreeSet 是 (用二叉树排序) Map AbstractMap 否 HashMap 是 (用二叉树排序) http://tb.blog.csdn.net/TrackBack.aspx?PostId=584112 List接口对Collection进行了简单的扩充,它的具体实现类常用的有ArrayList和LinkedList。你可以将任何东西放到一个List容器中,并在需要时从中取出。ArrayList从其命名中可以看出它是一种类似数组的形式进行存储,因此它的随机访问速度极快,而LinkedList的内部实现是链表,它适合于在链表中间需要频繁进行插入和删除操作。在具体应用时可以根据需要自由选择。前面说的Iterator只能对容器进行向前遍历,而ListIterator则继承了Iterator的思想,并提供了对List进行双向遍历的方法。 Set接口也是Collection的一种扩展,而与List不同的时,在Set中的对象元素不能重复,也就是说你不能把同样的东西两次放入同一个Set容器中。它的常用具体实现有HashSet和TreeSet类。HashSet能快速定位一个元素,但是你放到HashSet中的对象需要实现hashCode()方法,它使用了前面说过的哈希码的算法。而TreeSet则将放入其中的元素按序存放,这就要求你放入其中的对象是可排序的,这就用到了集合框架提供的另外两个实用类Comparable和Comparator。一个类是可排序的,它就应该实现Comparable接口。有时多个类具有相同的排序算法,那就不需要在每分别重复定义相同的排序算法,只要实现Comparator接口即可。集合框架中还有两个很实用的公用类: Collections和Arrays。Collections提供了对一个Collection容器进行诸如排序、复制、查找和填充等一些非常有用的方法,Arrays则是对一个数组进行类似的操作。 Map是一种把键对象和值对象进行关联的容器,而一个值对象又可以是一个Map,依次类推,这样就可形成一个多级映射。对于键对象来说,像Set一样,一个Map容器中的键对象不允许重复,这是为了保持查找结果的一致性;如果有两个键对象一样,那你想得到那个键对象所对应的值对象时就有问题了,可能你得到的并不是你想的那个值对象,结果会造成混乱,所以键的唯一性很重要,也是符合集合的性质的。当然在使用过程中,某个键所对应的值对象可能会发生变化,这时会按照最后一次修改的值对象与键对应。对于值对象则没有唯一性的要求。你可以将任意多个键都映射到一个值对象上,这不会发生任何问题 (不过对你的使用却可能会造成不便,你不知道你得到的到底是那一个键所对应的值对象) 。Map有两种比较常用的实现: HashMap和TreeMap。HashMap也用到了哈希码的算法,以便快速查找一个键,TreeMap则是对键按序存放,因此它便有一些扩展的方法,比如firstKey(),lastKey()等,你还可以从TreeMap中指定一个范围以取得其子Map。键和值的关联很简单,用pub(Object key,Object value)方法即可将一个键与一个值对象相关联。用get(Object key)可得到与此key对象所对应的值对象。 http://zhidao.baidu.com/question/16113509.html

2012-09-25 · 1 min · 39 words · lcf

Java 流, Stream

Java 流, Stream IO流的分类: 根据流的数据对象来分: 高端流: 所有的内存中的流都是高端流,比如: InputStreamReader 低端流: 所有的外界设备中的流都是低端流,比如InputStream,OutputStream 如何区分: 所有的流对象的后缀中包含Reader或者Writer的都是高端流,反之,则基本上为低端流,不过也有例外,比如PrintStream就是高端流 根据数据的流向来分: 输出流: 是用来写数据的,是由程序 (内存) ->外界设备 输入流: 是用来读数据的,是由外界设备->程序 (内存) 如何区分: 一般来说输入流带有Input,输出流带有Output 根据流数据的格式来分: 字节流: 处理声音或者图片等二进制的数据的流,比如InputStream 字符流: 处理文本数据 (如txt文件) 的流,比如InputStreamReader 如何区分: 可用高低端流来区分,所有的低端流都是字节流,所有的高端流都是字符流 根据流数据的包装过程来分: 原始流: 在实例化流的对象的过程中,不需要传入另外一个流作为自己构造方法的参数的流,称之为原始流。 包装流: 在实例化流的对象的过程中,需要传入另外一个流作为自己构造方法发参数的流,称之为包装流。 如何区分: 所以的低端流都是原始流,所以的高端流都是包装流 流是 Java 中最重要的基本概念之一。文件读写、网络收发、进程通信,几乎所有需要输入输出的地方,都要用到流。 流是做什么用的呢?就是做输入输出用的。为什么输入输出要用"流"这种方式呢?因为程序输入输出的基本单位是字节,输入就是获取一串字节,输出就是发送一串字节。但是很多情况下,程序不可能接收所有的字节之后再进行处理,而是接收一点处理一点。比方你下载魔兽世界,不可能全部下载到内存里再保存到硬盘上,而是下载一点就保存一点。这时,流这种方式就非常适合。 在 Java 中,每个流都是一个对象。流分为两种: 输入流(InputStream)和输出流(OutputStream)。对于输入流,你只要从流当中不停地把字节取出来就是了;而对于输出流,你只要把准备好的字节串传给它就行。 __Java 程序 | | 外部系统 –|–(输入流)–> 处理逻辑 –(输出流)—|–> 外部系统 |_________________________________| 流对象是怎么获得的呢?不同的外部系统,获取流的方式也不同。例如,文件读写就要创建 FileInputStream/FileOutputStream 对象,而网络通信是通过 Socket 对象来获取输入输出流的。一般来说,如果一个类有 getInputStream() 或 getOutputStream() 这样的方法,就表明它是通过流对象来进行输入输出的。 InputStream 是输入流,下面是一个通过 InputStream 读取文件的例子: import java.io.File; ...

2012-09-25 · 3 min · 635 words · lcf

stop() 和 suspend() 方法为何不推荐使用?

stop() 和 suspend() 方法为何不推荐使用? http://blog.csdn.net/yakihappy/article/details/3979912 反对使用stop(),是因为它不安全。它会解除由线程获取的所有锁定,当在一个线程对象上调用stop()方法时,这个线程对象所运行的线程就会立即停止,假如一个线程正在执行: synchronized void { x = 3; y = 4;}由于方法是同步的,多个线程访问时总能保证x,y被同时赋值,而如果一个线程正在执行到x = 3;时,被调用了 stop()方法,即使在同步块中,它也干脆地stop了,这样就产生了不完整的残废数据。而多线程编程中最最基础的条件要保证数据的完整性,所以请忘记线程的stop方法,以后我们再也不要说"停止线程"了。而且如果对象处于一种不连贯状态,那么其他线程能在那种状态下检查和修改它们。结果 很难检查出真正的问题所在。 suspend()方法容易发生死锁。调用suspend()的时候,目标线程会停下来,但却仍然持有在这之前获得的锁定。此 时,其他任何线程都不能访问锁定的资源,除非被"挂起"的线程恢复运行。对任何线程来说,如果它们想恢复目标线程,同时又试图使用任何一个锁定的资源,就 会造成死锁。所以不应该使用suspend(),而应在自己的Thread类中置入一个标志,指出线程应该活动还是挂起。若标志指出线程应该挂起,便用 wait()命其进入等待状态。若标志指出线程应当恢复,则用一个notify()重新启动线程。

2012-09-25 · 1 min · 23 words · lcf

corba, ejb, webservice, rest分布式 区别

corba, ejb, webservice, rest分布式 区别 Corba,还是EJB,都有一些共同点: 通过专有的网络协议通讯 不能跨平台调用 通过分布式对象调用来实现分布式架构,换句话来说就是,分布式架构是绑定在面向对象的机制上的 分布式对象架构的缺陷在EJB2时代被充分暴露了出来 web services有一些明显不同于Corba和EJB分布式对象架构的特征: 通过标准SOAP协议通讯,一般走HTTP通道 能够跨平台调用 通讯格式是xml文本,而不是二进制数据格式 通过RPC机制来实现分布式调用,而不是通过面向对象机制实现分布式调用 REST也是一种分布式系统的架构风格,那么REST和上面这些分布式架构有哪些明显的区别呢? REST走的是HTTP协议,并且充分利用或者说极端依赖HTTP协议 Corba和EJB是采用专有的二进制协议,SOAP可以但不依赖HTTP,并且仅仅使用HTTP POST。 REST是基于HTTP抽象资源的分布式调用,换句话来说,就是分布式调用是绑定在资源的操作上面的。 分布式架构 协议 调用方式 Corba架构 专有二进制协议 对象的CRUD操作 EJB架构 专有二进制协议 对象的CRUD操作 Web Services SOAP协议 RPC方式 REST HTTP协议 对资源的CRUD操作 REST最大的特点是什么呢?REST是为通过HTTP协议来进行分布式调用量身定造的架构 REST是专门为分布式调用设计的架构,在REST里面,分布式是通过对资源的操作来实现的,不是像EJB那样通过对象的方法调用来实现的。资源是一种抽象的概念,资源被映射到相应的一套URL规则上面了。所以资源只和URL相关,而与具体实现无关,因此REST具有更好的解藕性。

2012-09-25 · 1 min · 39 words · lcf

Dmidecode,在 Linux 下获取硬件信息

‘Dmidecode,在 Linux 下获取硬件信息’ http://linuxtoy.org/archives/dmidecode.html Dmidecode 应该在主流的 Linux 发行版中都可以找到,因此你只需通过所用发行版的包管理器安装即可,如: pacman -S dmidecode # Arch Linux emerge -av dmidecode # Gentoo aptitude install dmidecode # Debian/Ubuntu yum install dmidecode # Fedora 不带选项执行 dmidecode 通常会输出所有的硬件信息,以下是在笔者机器上执行 dmidecode 后所得到的结果 (部分) : # dmidecode 2.10 SMBIOS 2.3 present. 26 structures occupying 1285 bytes. Table at 0x000FC010. Handle 0x0000, DMI type 0, 24 bytes BIOS Information Vendor: American Megatrends Inc. Version: 080012 Release Date: 02/06/2007 Address: 0xF0000 Runtime Size: 64 kB ROM Size: 512 kB ... Dmidecode 有个很有用的选项 -t,可以按指定类型输出相关信息,假如要获得处理器方面的信息,则可以执行 ...

2012-09-25 · 1 min · 201 words · lcf

linux 内存

linux 内存 linux 查看内存 top free -h # 内存的更具体的使用情况 cat /proc/meminfo dmidecode -t memory dmidecode |grep -A16 "Memory Device$" 进程内存占用 top ps aux | grep containerd ps -o pid,user,%mem,rss,vsz,comm -C containerd pmap PID #ps ps -e -o 'pid,comm,args,pcpu,rsz,vsz,stime,user,uid' 其中rsz是是实际内存 ps -e -o 'pid,comm,args,pcpu,rsz,vsz,stime,user,uid' | grep oracle | sort -nrk5 其中rsz为实际内存,上例实现按内存排序,由大到小 sudo pacman -S htop # Arch Linux htop # 实时查看 containerd 服务的资源占用 systemd-cgtop # 只看 containerd 相关的 systemd-cgtop | grep containerd yay -S smem sudo smem -t -k -c "pid user command rss pss uss" | grep containerd 内存映射 cat /proc/PID/maps cat /proc/PID/smaps free> total 跟物理内存不一致 系统启动时会初始化相关设备,该过程会占用内存,内核启动时,也会占用一部分的内存。 ...

2012-09-25 · 1 min · 98 words · lcf

XML Schema, XML DTD

XML Schema, XML DTD http://www.ibm.com/developerworks/cn/xml/x-sd/index.html 引言 XML DTD(XML的文档类型定义)是近几年来XML技术领域所使用的最广泛的一种模式。但是,由于XML DTD并不能完全满足XML自动化处理的要求,例如不能很好实现应用程序不同模块间的相互协调,缺乏对文档结构、属性、数据类型等约束的足够描述等等,所以W3C于2001年5月正式推荐XML Schema为XML 的标准模式。显然,W3C希望以XML Schema来作为XML模式描述语言的主流,并逐渐代替XML DTD。那么XML Schema与XML DTD相比到底有哪些优势呢,XML DTD是否真的会在XML的模式描述领域中逐渐消失呢? 回页首 XML模式与XML格式 XML模式是指用来描述XML结构、约束等因素的语言,例如XML Schema、XML DTD、XDR,SOX等等。XML格式则是XML文档本身所具有的格式。本文以XML Schema来代表W3C所推荐的XML Schema模式标准,而以"XML模式"来代表所有的XML模式描述语言。 从模式的描述语言来说,XML Schema和XML DTD都属于语法模式。与概念模式不同,语法模式在对同一事物描述时,可以采用不同的语法,例如在对关系模式描述时,无论是使用XML Schema还是XML DTD,都既可以用元素也可以用属性来描述关系模式的列。 模式必须以某种格式来表示,XML Schema的格式与XML DTD的格式有着非常明显的区别,XML Schema事实上也是XML的一种应用,也就是说XML Schema的格式与XML的格式是完全相同的,而作为SGML DTD的一个子集,XML DTD具有着与XML格式完全不同的格式。这种区别会给XML Schema的使用带来许多好处: XML用户在使用XML Schema的时候,不需要为了理解XML Schema而重新学习,节省了时间; 由于XML Schema本身也是一种XML,所以许多的XML编辑工具、API 开发包、XML语法分析器可以直接的应用到XML Schema,而不需要修改。 作为XML的一个应用,XML Schema理所当然的继承了XML的自描述性和可扩展性,这使得XML Schema 更具有可读性和灵活性。 由于格式完全与XML一样,XML Schema除了可以像XML一样处理外,也可以同它所描述的XML文档以同样的方式存储在一起,方便管理。 XML Schema与XML格式的一致性,使得以XML为数据交换的应用系统之间,也可以方便的进行模式交换。 XML有非常高的合法性要求,XML DTD对XML的描述,往往也被用作验证XML合法性的一个基础,但是XML DTD本身的合法性却缺少较好的验证机制,必需独立处理。XML Schema则不同,它与XML有着同样的合法性验证机制。

2012-09-25 · 1 min · 55 words · lcf

Synchronized 和 java.util.concurrent.locks.Lock 的区别

Synchronized 和 java.util.concurrent.locks.Lock 的区别 主要相同点: Lock 能完成 Synchronized 所实现的所有功能。 主要不同点: Lock 有比 Synchronized 更精确的线程语义和更好的性能。Synchronized 会自动释放锁,但是 Lock 一定要求程序员手工释放,并且必须在 finally 从句中释放。 synchronized 修饰方法 synchronized 修饰方法时 表示同一个对象在不同的线程中表现为同步队列 如果实例化不同的对象 那么synchronized就不会出现同步效果了。 对象的锁 所有对象都自动含有单一的锁。 JVM负责跟踪对象被加锁的次数。如果一个对象被解锁,其计数变为0。在任务 (线程) 第一次给对象加锁的时候,计数变为1。每当这个相同的任务 (线程) 在此对象上获得锁时,计数会递增。 只有首先获得锁的任务 (线程) 才能继续获取该对象上的多个锁。 每当任务离开一个 synchronized 方法,计数递减,当计数为0的时候,锁被完全释放,此时别的任务就可以使用此资源。 synchronized同步块 2.1同步到单一对象锁 当使用同步块时,如果方法下的同步块都同步到一个对象上的锁,则所有的任务 (线程) 只能互斥的进入这些同步块。 Resource1.java演示了三个线程 (包括main线程) 试图进入某个类的三个不同的方法的同步块中,虽然这些同步块处在不同的方法中,但由于是同步到同一个对象 (当前对象 synchronized (this)) ,所以对它们的方法依然是互斥的。 比如 Class Test{ public static User user=null; Public synchronized void add(User u){ user=u; Dao.save(user) } } //如果在线程1中 Test test=new Test(); User u=new User(); u.setUserName("liaomin"); u.setUserPassword("liaomin"); Test.add(u); //如果在线程2中 Test tes1t=new Test(); User u1=new User(); u1.setUserName("huqun"); u1.setUserPassword("huqun"); Tes1t.add(u1); 那么 现在线程1 和线程2同时启动 如果对象new的不是同一个Test ...

2012-09-25 · 1 min · 158 words · lcf

linux下用adb为android手机批量安装软件

linux下用adb为android手机批量安装软件 通常大家安装软件都是从Andorid Market或者从网上下载到手机本地安装,这有两个问题,第一个情况碰到网速慢,那要急死,第二种情况是安装的太慢,如果软件多的话,手指累死,那么,就用adb安装吧,看我的操作情况: 首先把以前安装的软件备份到电脑,比如~/backup/,接着,打开电脑上的终端,取得root权限, cd adb ./adb start-server 打开另一个终端,默认用户权限 $ cd adb $ sh install.sh (-sh里面的内容如这样: ./adb install ~/backup/***.apk……,把你要装的软件都这样编辑,一行一个软件) ok,等着吧,安装完,切换到第一个终端,执行 ./adb kill-server 安全移除手机,看看手机上是不是已经显示你安装的软件了,呵呵

2012-09-24 · 1 min · 23 words · -

Java GenNode结构

Java GenNode结构 GenNode.java package com.http; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; /** * The Class Node. */ public class GenNode implements Serializable { /** * The Constant serialVersionUID. */ private static final long serialVersionUID = 1L; public static final String ATTRIBUTE = "attribute"; /** * The name. */ private String name; /** * The parent. */ private GenNode parent; /** * The value. */ private String value; /** * The attribute map. */ private Map<String, String> attributes; /** * The elements. */ private Map<String, List<GenNode>> elements = new HashMap<String, List<GenNode>>(); /** * Instantiates a new node. * * @param parent the parent * @param name the name */ public GenNode(GenNode parent, String name) { this.parent = parent; this.name = name; } /** * Instantiates a new node. * * @param parent the parent * @param name the name * @param value the value */ public GenNode(GenNode parent, String name, String value) { this.name = name; this.parent = parent; this.value = value; } /** * Instantiates a new node. * * @param parent the parent * @param name the name * @param value the value */ public GenNode(GenNode parent, String name, String value, NamedNodeMap atts) { this.name = name; this.parent = parent; this.value = value; this.setAttributes(atts); } /** * Adds the child. * * @param name the name * @param value the value * @return the node */ public GenNode addChild(String name, String value) { GenNode child = new GenNode(this, name, value); List<GenNode> list = null; if (!elements.containsKey(name)) { list = new ArrayList<GenNode>(); elements.put(name, list); } else { list = elements.get(name); } list.add(child); return child; } public GenNode addChild(GenNode node) { String name = node.getName(); List<GenNode> list = null; if (!elements.containsKey(name)) { list = new ArrayList<GenNode>(); elements.put(name, list); } else { list = elements.get(name); } list.add(node); return node; } /** * Gets the name. * * @return the name */ public String getName() { return name; } /** * Sets the name. * * @param name the new name */ public void setName(String name) { this.name = name; } /** * Gets the parent. * * @return the parent */ public GenNode getParent() { return parent; } /** * Sets the parent. * * @param parent the new parent */ public void setParent(GenNode parent) { this.parent = parent; } /** * Gets the value. * * @return the value */ public String getValue() { return value; } /** * Sets the value. * * @param value the new value */ public void setValue(String value) { this.value = value; } /** * Gets the attributes of this GenNode. * * @return the Map */ public Map<String, String> getAttributes() { return this.attributes; } /** * Sets the attributes. * * @param atts */ public void setAttributes(NamedNodeMap atts) { if (attributes == null) { attributes = new HashMap<String, String>(); } attributes.clear(); for (int i = 0; i < atts.getLength(); i++) { Node attrNode = atts.item(i); this.attributes .put(attrNode.getNodeName(), attrNode.getNodeValue()); } } /** * Gets the attributes of this GenNode. * * @return the Map */ public List<GenNode> getAttributeNodes() { return getChildren(ATTRIBUTE); } /** * Gets the attribute key set. * * @return the attribute key set */ public Set<String> getAttributesKeySet() { Set<String> set = new HashSet<String>(); List<GenNode> list = getAttributeNodes(); if (list != null && !list.isEmpty()) { for (GenNode node : list) { set.add(node.getName()); } } return set; } /** * Gets the attribute. * * @param name the name * @return the attribute */ public GenNode getAttribute(String name) { return getChild(ATTRIBUTE + "_" + name); } /** * Gets the attribute value. * * @param name the name * @return the attribute value */ public String getAttributeValue(String name) { GenNode node = getChild(ATTRIBUTE + "_" + name); return node != null ? node.getValue() : null; } /** * Size. * * @return the int */ public int size() { return elements.size(); } /** * Gets the elements. * * @param name the name * @return the elements */ protected List<GenNode> getElements(String name) { return elements.get(name); } /** * Gets the children. * * @param name the name * @return the children */ public List<GenNode> getChildren(String name) { List<NodePath> list = NodeUtil.getNodePaths(name); List<GenNode> children = null; int len = list.size(); if (len > 0) { int index = 0; GenNode tmpNode = this; for (NodePath path : list) { index++; children = tmpNode.getElements(path.getKey()); if (children == null) { return null; } if (children.isEmpty()) { tmpNode = null; break; } else if (index < len) { if (path.getIndex() < children.size()) { tmpNode = children.get(path.getIndex()); } else { tmpNode = null; } } if (tmpNode == null) { children = null; break; } } } return children; } /** * Gets the child. * * @param name the name * @return the child */ public GenNode getChild(String name) { List<NodePath> list = NodeUtil.getNodePaths(name); GenNode tmpNode = null; int len = list.size(); if (len > 0) { int index = list.get(len - 1).getIndex(); tmpNode = getChild(name, index); } return tmpNode; } /** * Gets the child value. * * @param name the name * @return the child value */ public String getChildValue(String name) { String value = null; GenNode node = getChild(name); if (node != null) { value = node.getValue(); } return value; } /** * Gets the child. * * @param name the name * @param index the index * @return the child */ public GenNode getChild(String name, int index) { GenNode rtnNode = null; List<GenNode> children = getChildren(name); if (children != null && !children.isEmpty() && children.size() > index) { rtnNode = children.get(index); } return rtnNode; } /** * Gets the child value. * * @param name the name * @param index the index * @return the child value */ public String getChildValue(String name, int index) { String value = null; GenNode node = getChild(name, index); if (node != null) { value = node.getValue(); } return value; } /** * Gets the full name. * * @return the full name */ public String getFullName() { String fullName = this.name; int index = 0; if (parent != null) { fullName = NodeUtil.makePath(parent.getFullName(), fullName); List<GenNode> list = parent.getElements(this.name); index = list.indexOf(this); } fullName = NodeUtil.makePath(fullName, index); return fullName; } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ public String toString() { StringBuffer sb = new StringBuffer(); sb.append("FullName = " + getFullName()); sb.append("; Name = " + getName()); sb.append("; Value = " + getValue()); return sb.toString(); } public Map getElements() { return elements; } } NodePath.java ...

2012-09-24 · 9 min · 1894 words · lcf

linux 时区,时间

linux 时区,时间 # 把硬件时间设置成系统时间 hwclock --hctosys # 把系统时间设置成硬件 hwclock --systohc # 设置硬件时间 hwclock --set --date="mm/dd/yy hh:mm:ss" # 修改系统时间 date -s "dd/mm/yyyy hh:mm:ss" timedatectl 设置时区 # 查看系统时间方面的各种状态 timedatectl timedatectl status # 列出所有时区 timedatectl list-timezones # 设置系统时区为上海 timedatectl set-timezone Asia/Shanghai timesync sudo systemctl restart systemd-timesyncd systemctl status systemd-timesyncd timedatectl show-timesync timedatectl timesync-status https://www.linuxuprising.com/2019/07/how-to-set-timezone-and-enable-network.html timedatectl set-local-rtc 1 # 将硬件时钟调整为与本地时钟一致, 0 为设置为 UTC 时间 其实不考虑各个发行版的差异化, 从更底层出发的话, 修改时间时区比想象中要简单: cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime ...

2012-09-24 · 2 min · 397 words · lcf

UML

UML 时序图, Sequence Diagram Use Case Diagram 类图, Class Diagram Object Diagram 活动图, Activity Diagram 组件图, Component Diagram 部署图, Deployment Diagram 状态图, State Diagram Timing Diagram 部署图 部署图描述的是系统运行时的结构,展示了硬件的配置及其软件如何部署到网络结构中。一个系统模型只有一个部署图,部署图通常用来帮助理解分布式系统。 组件图 https://zhuanlan.zhihu.com/p/78244670 https://plantuml.com/zh/component-diagram 组件图:组件图是 UML(统一建模语言)中的一种结构图,用于可视化系统组件的组织和关系。这些图有助于将复杂的系统分解成易于管理的组件,展示它们之间的相互依存关系,确保高效的系统设计和架构。 Component diagram shows components, provided and required interfaces, ports, and relationships between them. This type of diagrams is used in Component-Based Development (CBD) to describe systems with Service-Oriented Architecture (SOA). Component-based development is based on assumptions that previously constructed components could be reused and that components could be replaced by some other “equivalent” or “conformant” components, if needed. The artifacts that implement component are intended to be capable of being deployed and re-deployed independently, for instance to update an existing system. ...

2012-09-24 · 2 min · 261 words · -

Java Thread/线程

Java Thread/线程 java的线程是映射到操作系统原生线程之上的 java线程阻塞的代价 java的线程是映射到操作系统原生线程之上的,如果要阻塞或唤醒一个线程就需要操作系统介入,需要在户态与核心态之间切换,这种切换会消耗大量的系统资源,因为用户态与内核态都有各自专用的内存空间,专用的寄存器等,用户态切换至内核态需要传递给许多变量、参数给内核,内核也需要保护好用户态在切换时的一些寄存器值、变量等,以便内核态调用结束后切换回用户态继续工作。 如果线程状态切换是一个高频操作时,这将会消耗很多CPU处理时间; 如果对于那些需要同步的简单的代码块,获取锁挂起操作消耗的时间比用户代码执行的时间还要长,这种同步策略显然非常糟糕的。 线程状态 线程共包括以下5种状态。 新建状态 (New): 线程对象被创建后,就进入了新建状态。例如,Thread thread = new Thread()。 就绪状态(Runnable): 也被称为 “可执行状态”。线程对象被创建后,其它线程调用了该对象的start()方法,从而来启动该线程。例如,thread.start()。处于就绪状态的线程,随时可能被CPU调度执行。 运行状态(Running): 线程获取CPU权限进行执行。需要注意的是,线程只能从就绪状态进入到运行状态。 阻塞状态(Blocked): 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种: 等待阻塞 – 通过调用线程的 wait() 方法,让线程等待某工作的完成。 同步阻塞 – 线程在获取 synchronized 同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态。 其他阻塞 – 通过调用线程的 sleep() 或 join() 或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。 死亡状态(Dead): 线程执行完了或者因异常退出了run()方法,该线程结束生命周期。 这 5 种状态涉及到的内容包括 Object 类, Thread 类, 和 synchronized 关键字。 这些内容我们会在后面的章节中逐个进行学习。 Object 类,定义了 wait(), notify(), notifyAll( ) 等休眠/唤醒函数。 Thread 类,定义了一些列的线程操作函数。例如,sleep() 休眠函数, interrupt() 中断函数, getName() 获取线程名称等。 synchronized,是关键字;它区分为 synchronized 代码块和 synchronized 方法。 synchronized 的作用是让线程获取对象的同步锁。 在后面详细介绍 wait(), notify() 等方法时,我们会分析为什么 “wait(), notify() 等方法要定义在 Object 类,而不是 Thread 类中” ...

2012-09-22 · 4 min · 849 words · -

java enum/枚举

java enum/枚举 Java 5.0 引入了枚举类型,语法参见 JLS 8.9 枚举比较 // 枚举可以用 "==" 和 equals 比较 GameEnum s1 = GameEnum.BIG; GameEnum s2 = GameEnum.BIG; GameEnum ss1 = GameEnum.SMALL; System.out.println("s1 == s2: " + (s1 == s2)); //true System.out.println("s1.equals(s2): " + (s1.equals(s2))); //true System.out.println("s1 == ss1: " + (s1 == ss1)); //false System.out.println("s1.equals(ss1): " + (s1.equals(ss1))); //false // 字符串 > 枚举 Blah val = Blah.valueOf("A") package com.ljq.test; 普通枚举 定义一个功能简单的枚举类型,跟定义一个简单的类很相似,例如 跟类定义一样,枚举类型可以单独放在一个文件里,当一个枚举类型用public修饰时,它对其他包可见,否则只对同一个包中的类可见,这和类定义是一样的。 标识符 MONDAY, TUESDAY等就称为枚举常量 (enumeration constants) 每一个枚举常量被隐式的声明成Day的一个public、static成员,而且其类型为Day,亦就是说这些常量是self-typed的 ...

2012-09-22 · 8 min · 1622 words · -

ultra mobile

ultra mobile 换手机之后给手机写入 eSIM ultra mobile 用手机号和密码登录 切换到 ACCOUNT My SIM> Change Device Get an eSIM This is my new device 选择 我有 wifi 连接 然后需要等一段时间会自动切换掉安装 eSIM 页面

2012-09-22 · 1 min · 28 words · -

postgresql json jsonb

jpostgresql json jsonb postgresql—-JSON类型和函数 postgresql支持两种json数据类型:json和jsonb,而两者唯一的区别在于效率,json是对输入的完整拷贝,使用时再去解析,所以它会保留输入的空格,重复键以及顺序等。而jsonb是解析输入后保存的二进制,它在解析时会删除不必要的空格和重复的键,顺序和输入可能也不相同。使用时不用再次解析。两者对重复键的处理都是保留最后一个键值对。效率的差别:json类型存储快,使用慢,jsonb类型存储稍慢,使用较快。 注意:键值对的键必须使用双引号 从PostgreSQL 9.3开始,json就成了postgres里的一种数据类型,也就是和varchar、int一样,我们表里的一个字段的类型可以为json了。 与此同时,postgres还提供了jsonb格式,jsonb格式是json的二进制形式,二者的区别在于json写入快,读取慢,jsonb写入慢,读取快,但在操作上,二者是没有区别的。下面以jsonb为例。 创建表 假设我们要存储的json数据是这样的: { “id”: ID “name”:“名字”, “age”:年龄 } 建表语句如下: create table if not exists name_age ( info jsonb ) 好了,这样就创建了一张表,里面只有一个 info 字段,下面开始进行CRUD操作。 插入数据 插入数据可以直接以json格式插入: insert into name_age values(’{“id”:1,“name”:“小明”, “age”:18}’) 在json里插入新的key值gender,如下: SELECT info||’{“gender”:“男”}’::jsonb from name_age where (info-»‘id’)::int4 = 1 查询数据 Postgres里的查询需要用到查询符。比如说,我们要查询id为1的数据,语句如下: select info from name_age where info @> ‘{“id”:1}’::jsonb 用到了 @> 这个查询符,表明info当前这条记录里的顶层json中有没有id为1的key-value对;有的话则满足条件。 再来一个复杂一点的查询的,查询 age>16 的记录,并且只显示 name ,语句如下: select info->‘name’ from name_age where (info-»‘age’)::int4 > 16 关于详细运算符使用,请参考官方文档: 9.15. JSON Functions and Operators ...

2012-09-22 · 4 min · 716 words · -

Revolution OS操作系统革命

Revolution OS操作系统革命 操作系统革命的剧情简介 · · · · · · 内容简介(来自http://blog.9zi.com/post/1/979) : 在微软垄断下有一件东西永远它永远不会给你――真正的自由。也正是因为这个原因,不少先锋人物站出来反抗微软帝国,并努力建立一种新的操作系统――没有人为的限制,任何人都可以自由地使用。 为了记录这些人的艰苦历程,J.T.S. Moore拍摄了全新的记录片――REVOLUTON OS,向公众介绍这些建立Linux操作系统,奋起反抗垄断的斗士的人生经历。 现在微软已经明显感到了来自Linux的压力。微软的首席执行官去年6月公开表示: “Linux 是一种癌症!"。但这丝毫不能影响Linux发展的步伐。 REVOLUTION OS中记录了Linux的创建人Linus Torvalds以及Richard Stallman, Bruce Perens, Eric Raymond, Brian Behlendorf, Michael Tiemann, Larry Augustin, Frank Hecker, Rob Malda等人的生活经历或者采访记录。 http://movie.douban.com/subject/1437389/

2012-09-22 · 1 min · 37 words · -