169it科技资讯
169it -->


当前位置:  编程技术>软件工程/软件设计
本页文章导读:
    ▪(十)装饰器模式详解(与IO不解的情缘)                       作者:zuoxiaolong8810(左潇龙),转载请注明出处。               &nbs......
    ▪无锁编程:最简单例子      场景    假设存在这样一个情况:需要N个线程对一个全局的变量进行M次递增操作。首先想到的常常是,使用互斥量。当然在“无锁”的世界里,还有其它实现方式。话不多说,看代......
    ▪【虚拟化实战】网络设计之四Teaming       作者:范军 (Frank Fan) 新浪微博:@frankfan7   微信:frankfan7 Network teaming 这个概念在物理服务器中早就很普遍,我们往往会在物理服务器设置多个物理网卡的Team......
      最新IT科技资讯推荐: -1

[1](十)装饰器模式详解(与IO不解的情缘)
    来源: 互联网  发布时间: 2013-11-19

                 作者:zuoxiaolong8810(左潇龙),转载请注明出处。

                 LZ到目前已经写了九个设计模式,回过去看看,貌似写的有点凌乱,LZ后面会尽量改进。

                 那么本章LZ和各位读友讨论一个与JAVA中IO有着不解情缘的设计模式,装饰器模式。

                 定义:装饰模式是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

                 这一个解释,引自百度百科,我们注意其中的几点。

                 1,不改变原类文件。

                 2,不使用继承。

                 3,动态扩展。

                 上述三句话一语道出了装饰器模式的特点,下面LZ给出装饰器模式的类图,由于LZ的ROSE不是特别好用,各位凑合着看,先上图再解释。

                  从图中可以看到,我们装饰的是一个接口的任何实现类,而这些实现类也包括了装饰器本身,装饰器本身也可以再被装饰。

                  另外,这个类图只是装饰器模式的完整结构,但其实里面有很多可以变化的地方,LZ给出如下两条。

                  1,Component接口可以是接口也可以是抽象类,甚至是一个普通的父类(这个强烈不推荐,普通的类作为继承体系的超级父类不易于维护)。

                  2,装饰器的抽象父类Decorator并不是必须的。

                 那么我们将上述标准的装饰器模式,用我们熟悉的JAVA代码给诠释一下。首先是待装饰的接口Component。

package com.decorator;

public interface Component {

	void method();
	
}

                 接下来便是我们的一个具体的接口实现类,也就是俗称的原始对象,或者说待装饰对象。

package com.decorator;

public class ConcreteComponent implements Component{

	public void method() {
		System.out.println("原来的方法");
	}

}

                 下面便是我们的抽象装饰器父类,它主要是为装饰器定义了我们需要装饰的目标是什么。

package com.decorator;

public abstract class Decorator implements Component{

	protected Component component;

	public Decorator(Component component) {
		super();
		this.component = component;
	}
}

                  再来便是我们具体的装饰器A和装饰器B。

package com.decorator;

public class ConcreteDecoratorA extends Decorator{

	public ConcreteDecoratorA(Component component) {
		super(component);
	}
	
	public void methodA(){
		System.out.println("被装饰器A扩展的功能");
	}

	public void method(){
		System.out.println("针对该方法加一层A包装");
		component.method();
		System.out.println("A包装结束");
	}
}
package com.decorator;

public class ConcreteDecoratorB extends Decorator{

	public ConcreteDecoratorB(Component inputStream) {
		super(inputStream);
	}
	
	public void methodB(){
		System.out.println("被装饰器B扩展的功能");
	}

	public void method(){
		System.out.println("针对该方法加一层B包装");
		component.method();
		System.out.println("B包装结束");
	}
}

                下面给出我们的测试类。我们针对多种情况进行包装。

package com.decorator;

public class Main {

	public static void main(String[] args) {
		Component component =new ConcreteComponent();//原来的对象
		System.out.println("------------------------------");
		component.method();//原来的方法
		ConcreteDecoratorA concreteDecoratorA = new ConcreteDecoratorA(component);//装饰成A
		System.out.println("------------------------------");
		concreteDecoratorA.method();//原来的方法
		concreteDecoratorA.methodA();//装饰成A以后新增的方法
		ConcreteDecoratorB concreteDecoratorB = new ConcreteDecoratorB(component);//装饰成B
		System.out.println("------------------------------");
		concreteDecoratorB.method();//原来的方法
		concreteDecoratorB.methodB();//装饰成B以后新增的方法
		concreteDecoratorB = new ConcreteDecoratorB(concreteDecoratorA);//装饰成A以后再装饰成B
		System.out.println("------------------------------");
		concreteDecoratorB.method();//原来的方法
		concreteDecoratorB.methodB();//装饰成B以后新增的方法
	}
}

                 下面看下我们运行的结果,到底是产生了什么效果。

               从此可以看到,我们首先是使用的原始的类的方法,然后分别让A和B装饰完以后再调用,最后我们将两个装饰器一起使用,再调用该接口定义的方法。

               上述当中,我们分别对待装饰类进行了原方法的装饰和新功能的增加,methodA和methodB就是新增加的功能,这些都是装饰器可以做的,当然两者并不一定兼有,但一般至少会有一种,否则也就失去了装饰的意义。

               另外,文章开篇就说道了IO与装饰器的情缘,相信各位就算不太清楚,也都大致听说过JAVA的IO是装饰器模式实现的,所以LZ也不再废话,在给出一个标准的模板示例以后,直接拿出IO的示例,我们真枪实弹的来。

               下面LZ直接给出IO包中的部分装饰过程,上面LZ加了详细的注释以及各个装饰器的功能演示,各位可以和上面标准的装饰器模式对比一下,LZ不得不感叹,IO与装饰器的孽缘。

package com.decorator;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.PushbackInputStream;
import java.io.PushbackReader;

public class IOTest {

	/* test.txt内容:
	 * hello world!
	 */
	public static void main(String[] args) throws IOException, ClassNotFoundException {
		//文件路径可自行更换
		final String filePath = "E:/myeclipse project/POITest/src/com/decorator/test.txt";
		
		//InputStream相当于被装饰的接口或者抽象类,FileInputStream相当于原始的待装饰的对象,FileInputStream无法装饰InputStream
		//另外FileInputStream是以只读方式打开了一个文件,并打开了一个文件的句柄存放在FileDescriptor对象的handle属性
		//所以下面有关回退和重新标记等操作,都是在堆中建立缓冲区所造成的假象,并不是真正的文件流在回退或者重新标记
		InputStream inputStream = new FileInputStream(filePath);
		final int len = inputStream.available();//记录一下流的长度
		System.out.println("FileInputStream不支持mark和reset:" + inputStream.markSupported());
		
		System.out.println("---------------------------------------------------------------------------------");
		
		/* 下面分别展示三种装饰器的作用BufferedInputStream,DataInputStream,PushbackInputStream,LZ下面做了三个装饰器的功能演示  */
		
		//首先装饰成BufferedInputStream,它提供我们mark,reset的功能
      
    
[2]无锁编程:最简单例子
    来源: 互联网  发布时间: 2013-11-19
场景

    假设存在这样一个情况:需要N个线程对一个全局的变量进行M次递增操作。首先想到的常常是,使用互斥量。当然在“无锁”的世界里,还有其它实现方式。话不多说,看代码:

测试代码

gcc_sync_test.c

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#define TEST_ROUND  20000
#define THREAD_NUM  10

#define SYNC
#define LOCKLESS

#ifndef LOCKLESS
	pthread_mutex_t mutex_lock;
#endif

static volatile int count = 0;

void *test_func(void *arg)
{
	int i = 0;
	for(i = 0; i < TEST_ROUND; i++){
#ifdef SYNC
#ifdef LOCKLESS
		__sync_fetch_and_add(&count, 1);
#else
		pthread_mutex_lock(&mutex_lock);
		count++;
		pthread_mutex_unlock(&mutex_lock);
#endif
#else
		count++;
#endif
	}
	return NULL;
}

int main(int argc, const char *argv[])
{
	pthread_t thread_ids[THREAD_NUM];
	int i = 0;

#ifndef LOCKLESS
	pthread_mutex_init(&mutex_lock, NULL);
#endif
	for(i = 0; i < sizeof(thread_ids)/sizeof(pthread_t); i++){
		pthread_create(&thread_ids[i], NULL, test_func, NULL);
	}

	for(i = 0; i < sizeof(thread_ids)/sizeof(pthread_t); i++){
		pthread_join(thread_ids[i], NULL);
	}

	printf("count=%d\r\n", count);
	return 0;
}
Makefile

CC=gcc
CFLAGS= -Wall
LIB= -lpthread
OBJS=gcc_sync_test.o 
SRCS=${OBJS:%.o=%.c}

TARGETS=.depend gcc_sync_test

all:$(TARGETS)

.depend:
	@$(CC) $(CFLAGS) -MM $(SRCS)  > .depend  

-include .depend

gcc_sync_test: $(OBJS)
	$(CC) $(CFLAGS) $^ $(LIB) -o $@
	@echo $@ > .gitignore

clean:
	rm -rf $(OBJS) $(TARGETS)

.c.o:
	$(CC) $(CFLAGS) -c $< -o $@

测试结果

    在源代码文件gcc_sync_test.c中,使用SYNC宏来控制是否启用线程间同步;在启用SYNC情况下,使用LOCKLESS宏来控制是否使用“无锁”方式,还是使用互斥量方式。

选择“无锁”方式,编译、运行程序可以得到正确的结果“count=200000”,这和使用互斥量方式得到的结果一样。如果感兴趣的话,可以试试不采用任何一种同步方案(即,注释掉SYNC宏的定义),可以发现输出的结果是不正确的,道理很显然。

结果分析

    那么,为什么不用phtread_mutex_lock也可以实现线程间同步?可以看到程序中使用了__sync_fetch_and_add在实现加法运算。__sync_fetch_and_add是GCC内建的原子操作,它的原理《GCC内建的原子操作》中已经做了简单的叙述。如果关注GCC是如何实现该原子操作的,可以通过生成汇编代码的方式来探究。

gcc -S gcc_sync_test.c
生成汇编代码gcc_sync_test.s。查看它,可以发现其中有如下代码:

   jmp .L2
.L3:
   lock addl $1, count(%rip)
   addl  $1, -4(%rbp)
.L2:
   cmpl  $19999, -4(%rbp)

其中,“lock addl $1, count(%rip)”中的lock既是关键所在。lock是一个指令前缀,Intel的手册上对其的解释是:

Causes the processor's LOCK# signal to be asserted during execution of the accompanying instruction (turns the instruction into an atomic instruction). In a multiprocessor environment, the LOCK# signal insures that the processor has exclusive use of any shared memory while the signal is asserted.

如果不使用原子操作__sync_fetch_and_add,直接进行count++的话,产生的汇编代码大致是这样的:

  jmp .L2 
.L3:
  movl  count(%rip), %eax
  addl  $1, %eax
  movl  %eax, count(%rip)
  addl  $1, -4(%rbp)
.L2:
  cmpl  $19999, -4(%rbp)
显然缺了lock指令前缀。


其它

    至于,为什么count变量要是volatile的,这是避免使用gcc优化选项后直接将M此循环的结果算出,影响了实例代码的显著性。读者可以自己尝试一下:去掉volatile修饰,gcc编译时使用-O2优化,不使用任何同步的情况下(不启用SYNC宏),似乎也能得到正确的结果。


作者:sahusoft 发表于2013-6-20 21:46:45 原文链接
阅读:44 评论:0 查看评论

    
[3]【虚拟化实战】网络设计之四Teaming
    来源: 互联网  发布时间: 2013-11-19

作者:范军 (Frank Fan) 新浪微博:@frankfan7   微信:frankfan7

Network teaming 这个概念在物理服务器中早就很普遍,我们往往会在物理服务器设置多个物理网卡的Teaming,除了防范因为网卡故障造成的单点故障之外,还有负载均衡的目的。

在虚拟环境中,绝大多数情况下无需为了容错或者负载均衡的目的,为一个虚拟机连接多个虚拟网卡。因为容错或者负载均衡的任务交付给虚拟交换机和其连接的多个物理网卡了。怎么来实现呢?这就需要在设置虚拟交换机上设置NetworkTeaming Policy。


五种策略选择中哪一种才适合你的环境?

Route based on originating virtual port
Route based on IP Hash (only one supported withStatic Etherchannel and Static 802.3ad)
Route based on Source MAC address
Route based on physical NIC load (Load BasedTeaming or LBT)
Use explicit failover order (Not a load balancingalgorithm)

除了Route based on IP Hash需要在物理交换机上设置Link Aggregation之外,其他的策略无需物理交换机上的特别设置。


情景一:

某小型公司因为成本的考虑,没有购买Enterprise Plus许可,所以使用vSphere  Standard  Switch。

建议:

采用Route based on originating virtual port

依据该VM连接在vSwitch的Port ID来决定把数据包传输到对应的物理网卡,快捷简单,无需VMKernel对数据包作任何多余的处理。


情景二:

某大型公司人员众多,使用vSphere Distributed Switch.    ESXi连接了六张1G物理网卡。有几个虚拟机作为公司的文件服务器,经常有员工抱怨访问文件服务器延时严重,有时一个文件很长时间打不开。

建议:

采用Route based on IP Hash (only onesupported with Static Etherchannel and Static 802.3ad)。但前提是物理交换机必须支持staticEtherchannel 或者static 802.3ad link aggregation并作相应设置。

这种策略可以最大程度上提高文件服务器的吞吐量,因为Etherchannel可以把多张物理网卡绑定为一个Channel,那么吞吐量就由原来的1G变为1G* Channel内的网卡数目

以上的举例是一种比较特别的情况,同时有多个客户端对文件服务器虚拟机发起文件访问,而且1G网卡的吞吐量不能满足需求。

如果你的应用大多数情况下是点对点的通讯,这意味着同一时间内仅能用到一个物理网卡,相比LBT而言,Routebased on IP Hash并不能带来特别的好处。


情景三:

某公司使用vSphere Distributed Switch.   ESXi连接了两张10G物理网卡。因为已经采用了LVS或者硬件设备实现了负载均衡,目前的虚拟环境中没有对网络吞吐量要求特别高的虚拟机。

建议:

采用Route based on physical NIC load (Load Based Teaming orLBT)

vSphere4.1 以后vDS支持该策略。连接在ESXi上某个物理网卡的使用超过了75%之后,数据包会自动发送到其他比较空闲的物理网卡,从而达到负载均衡的目的。注意虽然你设置了多个物理网卡,但某一个时刻数据包只通过某个特定的物理网卡。10G是该VM能获得的最大的吞吐量。

如果使用vDS,绝大多数情况下LBT是最佳选择。无需情景二中物理交换机的复杂配置。


参考:

NICteaming in ESXi/ESX(1004088)


    
最新技术文章:
▪主-主数据库系统架构    ▪java.lang.UnsupportedClassVersionError: Bad version number i    ▪eclipse项目出现红色叉叉解决方案
▪Play!framework 项目部署到Tomcat    ▪dedecms如何做中英文网站?    ▪Spring Batch Framework– introduction chapter(上)
▪第三章 AOP 基于@AspectJ的AOP    ▪基于插件的服务集成方式    ▪Online Coding开发模式 (通过在线配置实现一个表
▪观察者模式(Observer)    ▪工厂模式 - 程序实现(java)    ▪几种web并行化编程实现
▪机器学习理论与实战(二)决策树    ▪Hibernate(四)——全面解析一对多关联映射    ▪我所理解的设计模式(C++实现)——解释器模
▪利用规则引擎打造轻量级的面向服务编程模式    ▪google blink的设计计划: Out-of-Progress iframes    ▪FS SIP呼叫的消息线程和状态机线程
▪XML FREESWITCH APPLICATION 实现    ▪Drupal 实战    ▪Blink: Chromium的新渲染引擎
▪(十四)桥接模式详解(都市异能版)    ▪你不知道的Eclipse用法:使用Allocation tracker跟    ▪Linux内核-进程
▪你不知道的Eclipse用法:使用Metrics 测量复杂度    ▪IT行业为什么没有进度    ▪Exchange Server 2010/2013三种不同的故障转移
▪第二章 IoC Spring自动扫描和管理Bean    ▪CMMI简介    ▪目标检测(Object Detection)原理与实现(六)
▪值班总结(1)——探讨sql语句的执行机制    ▪第二章 IoC Annotation注入    ▪CentOS 6.4下安装Vagrant
▪Java NIO框架Netty1简单发送接受    ▪漫画研发之八:会吃的孩子有奶吃    ▪比较ASP和ASP.NET
▪SPRING中的CONTEXTLOADERLISTENER    ▪在Nginx下对网站进行密码保护    ▪Hibernate从入门到精通(五)一对一单向关联映
▪.NET领域驱动设计—初尝(三:穿过迷雾走向光    ▪linux下的块设备驱动(一)    ▪Modem项目工作总结
▪工作流--JBPM简介及开发环境搭建    ▪工作流--JBPM核心服务及表结构    ▪Eclipse:使用JDepend 进行依赖项检查
▪windows下用putty上传文件到远程Linux方法    ▪iBatis和Hibernate的5点区别    ▪基于学习的Indexing算法
▪设计模式11---设计模式之中介者模式(Mediator    ▪带你走进EJB--JMS编程模型    ▪从抽象谈起(二):观察者模式与回调
▪设计模式09---设计模式之生成器模式(Builder)也    ▪svn_resin_持续优化中    ▪Bitmap recycle方法与制作Bitmap的内存缓存
▪Hibernate从入门到精通(四)基本映射    ▪设计模式10---设计模式之原型模式(Prototype)    ▪Dreamer 3.0 支持json、xml、文件上传
▪Eclipse:使用PMD预先检测错误    ▪Jspx.net Framework 5.1 发布    ▪从抽象谈起(一):工厂模式与策略模式
▪Eclipse:使用CheckStyle实施编码标准    ▪【论文阅读】《Chain Replication for Supporting High T    ▪Struts2 Path_路径问题
▪spring 配置文件详解    ▪Struts2第一个工程helloStruts极其基本配置    ▪Python学习入门基础教程(learning Python)--2 Python简
▪maven springmvc环境配置    ▪基于SCRUM的金融软件开发项目    ▪software quality assurance 常见问题收录
▪Redis集群明细文档    ▪Dreamer 框架 比Struts2 更加灵活    ▪Maven POM入门
▪git 分支篇-----不断更新中    ▪Oracle非主键自增长    ▪php设计模式——UML类图
▪Matlab,Visio等生成的图片的字体嵌入问题解决    ▪用Darwin和live555实现的直播框架    ▪学习ORM框架—hibernate(二):由hibernate接口谈
▪(十)装饰器模式详解(与IO不解的情缘)    ▪无锁编程:最简单例子    ▪【虚拟化实战】网络设计之四Teaming
▪OSGi:生命周期层    ▪Javascript/Jquery——简单定时器    ▪java代码 发送GET、POST请求
▪Entity Framework底层操作封装(3)    ▪HttpClient 发送GET、POST请求    ▪使用spring框架,应用启动时,加载数据
▪Linux下Apache网站目录读写权限的设置    ▪单键模式的C++描述    ▪学习ORM框架—hibernate(一):初识hibernate
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2017,169IT.COM,E-mail:www_169it_com#163.com(请将#改为@)

浙ICP备11055608号