FireFox

Firefox Firefox socks proxy firefox 稳定版没有 about:config 选项. firefox beta 和 firefox nightly build 可以在地址栏输入 about:config 查找 proxy 关键字, 设置 socks5 proxy 需要设置三个 key network.proxy.socks: 192.168.9.1 network.proxy.socks_port: 1080 network.proxy.socks_remote_dns: true network.proxy.type: 1 ubuntu install firefox https://support.mozilla.org/en-US/kb/install-firefox-linux#w_install-firefox-deb-package-for-debian-based-distributions-recommended

2013-07-15 · 1 min · 36 words · -

qmail sendmail postfix

qmail sendmail postfix http://liguxk.blog.51cto.com/129038/155491 关于 sendmail/qmail/postfix 孰优孰劣,以及部署邮件系统的时候该选哪一个的讨论已经重复了千百次了。但事实往往并不是A好B坏,或B好A坏,必须根据场合和应用的要求来定。但虽然如此,大多数人还是需要一个相对公平的评价,以引导邮件系统的部署。 自己一直很慎重于回答这类问题,以免引发不必要的争论甚至矛盾,但还是必须面对这个问题做一定的分析和比较的,否则很多朋友经常会问"到底用哪个好?",却拿不出完整的答案。 首先看看三个MTA的历史… MTAs的发展历史 Sendmail 毫无疑问,sendmail是最古老的MTA之一。它比 qmail和 postfix要古老得多。最早它诞生的时候, Internet还没有被标准化,当时主机之间使用的是UUCP技术来交换邮件。 它被设计得比较灵活,便于配置和运行于各种类型的机器。 Qmail qmail是新生一代的MTA代表,它以速度快、体积小、易配置安装等特性而著称。作者D. J. Bernstein(djb)是一个数学教授,富有传奇色彩。djb于1995年开发qmail,1996年发布0.70版,并使用了多种当时比较先进的技术,包括Maildir,与sendmail单个binary不同的模块化设计,权限分离,以及使用了大量由djb编写的配套工具,如daemontools,ucsip-tcp等。 qmail迅速成为了Internet上最有名的MTA,使用者众。 Postfix Postfix作者是Wietse Venema,一名著名的安全专家。最早postfix起源于1996年,当时venema 在美国IBM研究中心负责研究更安全的邮件系统,当时称为Vmailer。后因为商标问题于1998年11月正式更名为Postfix Postfix以替代sendmail为目的,并提供了一个更安全、更高性能的灵活的体系。它同样也采用模块化设计,使用了大量优秀的技术,以达到安全的目的。由于作者的设计理念独到,经过7,8年时间,Postfix现今已发展成为功能非常丰富,扩展性和安全性强的优秀MTA。 概括的比较 以下的分析主要基于我在CASA上发的一个小文章,对sendmail/qmail/postfix做了一个概括性的比较。 sendmail sendmai功能非常强大,很多先进功能在sendmail上都最先有实现。sendmail里的Milter技术是一个非常好的框架,目前postfix及qmail仍然没有官方发布的方案比milter要好。 但sendmail也有典型的历史问题,只有一个binary程序,需要sid权限,m4配置文件复杂难懂。这些是是阻碍sendmail更好发展的一些客观问题。客观来说,调教得好的sendmail,其性能也是相当不俗的,据一个国外的Unix杂志称,在solaris+内存文件系统+带电池的raid系统下,sendmail能达到惊人的287封/秒的注入速度! 目前sendmail比较适合那些老用户,因为他们习惯了sendmail的应用环境和配置。 qmail qmail体积非常小巧,source的gz包大概只有260多K,是三大MTA中最小的!模块化设计,避免了sid问题,基本功能齐全。配置相对sendmail而言,简单了很多,而且用户非常广泛。而且补丁和插件非常多,例如著名的vpopmail,netqmail,以及qmail-ldap等。 但qmail有几个问题,一是djb已经5,6年没有继续开发了,补丁的良莠不齐及版本依赖是非常麻烦的事,这对初学者极为不利。二是功能扩充需要补丁来完成,扩展能力不足。 总体上qmail依然是个非常不错的选择。对于希望了解mta原理,或希望修改mta代码的爱好者,qmail是值得推荐的。对于需要建立中小型邮件系统的用户也同样适合。而对于需要丰富功能却不想面对补丁困难,或者需要建立大型的系统,qmail不太合适,需要更丰富的经验和技术。 postfix postfix如今已经独树一帜,流水线、模块化的设计,兼顾了效率和功能。灵活的配置和扩展,使得配置postfix变得富有趣味。其主要的特点是速度快、稳定,而且配置/功能非常强大,并和sendmail类似,提供了与外部程序对接的API/protocol。尤其是配置部分,可以说是一扫qmail和sendmail的各自缺点。 但postfix管理及配置的入门依然需要一定的工夫,必须仔细阅读官方文档。postfix另一个优势是至今依然保持活跃的开发工作,而且稳步发展,适合高流量大负载的系统,扩充能力较强。 大规模应用例子 国内若干个大型emailISP (如163.net/tom.com/163.com及sohu等) 过去都使用qmail,后来全部更换成postfix。 新浪使用qmail,yahoo使用qmail。但这些已经不是普通的qmail了。 技术层面的分析 这里仅探讨一些典型的技术特点,从这些特点可以看出每个MTA设计的异同,主要讨论的焦点是qmail和postfix。 磁盘I/O 从队列文件的读写来看,qmail处理每一封邮件时,都至少需要建立3个文件,mess, intd, info等。而Postfix使用的是单队列文件设计,因此磁盘I/O的开销要比qmail小得多,如果仅仅从这个方面考虑,postfix的队列是qmail的2-4倍那么快。 从我过去的一个qmail vs postfix对比测试中,也可以发现这个问题。 数据同步 如果从MTA对待操作系统的文件是否安全写入磁盘的策略来看,qmail和postfix也是不同的。Postfix使用的是随机写,并且需要写入完成并安全同步到磁盘后才算完成。而qmail的写入则是即刻执行的,因此它将等待数据安全写入磁盘后才返回。对于高流量的系统而言,这将导致性能问题。 此外,Postfix的队列对于不要使用softupdate,除非是有磁盘后写电池。 扩充能力 sendmail有着非常好的扩充能力,支持众多的特性,功能可谓豪华。包括频率控制到集群支持应有尽有。而milterAPI则更加使sendmail的灵活性发挥至极,通过milter,用户可以对邮件几乎所有的参数进行控制!但是在存储方面,由于只支持mbox,会有一定的问题。 ...

2013-07-14 · 1 min · 110 words · -

ReentrantReadWriteLock

ReentrantReadWriteLock 一、ReentrantReadWriteLock与ReentrantLock 说到ReentrantReadWriteLock,首先要做的是与ReentrantLock划清界限。它和后者都是单独的实现,彼此之间没有继承或实现的关系。 ReentrantLock 实现了标准的互斥操作,也就是一次只能有一个线程持有锁,也即所谓独占锁的概念。显然这个特点在一定程度上面减低了吞吐量,实际上独占锁是一种保守的锁策略,在这种情况下任何"读/读",“写/读”,“写/写"操作都不能同时发生。但是同样需要强调的一个概念是,锁是有一定的开销的,当并发比较大的时候,锁的开销就比较可观了。所以如果可能的话就尽量少用锁,非要用锁的话就尝试看能否改造为读写锁。 ReadWriteLock 描述的是: 一个资源能够被多个读线程访问,或者被一个写线程访问,但是不能同时存在读写线程。也就是说读写锁使用的场合是一个共享资源被大量读取操作,而只有少量的写操作 (修改数据) 。清单0描述了ReadWriteLock的API。 // 清单0 ReadWriteLock 接口 public interface ReadWriteLock { Lock readLock(); Lock writeLock(); } 清单0描述的ReadWriteLock结构,这里需要说明的是ReadWriteLock并不是Lock的子接口,只不过ReadWriteLock借助Lock来实现读写两个视角。在ReadWriteLock中每次读取共享数据就需要读取锁,当需要修改共享数据时就需要写入锁。看起来好像是两个锁,但其实不尽然,下文会指出。 二、ReentrantReadWriteLock的特性 ReentrantReadWriteLock有以下几个特性: 公平性 非公平锁 (默认) 这个和独占锁的非公平性一样,由于读线程之间没有锁竞争,所以读操作没有公平性和非公平性,写操作时,由于写操作可能立即获取到锁,所以会推迟一个或多个读操作或者写操作。因此非公平锁的吞吐量要高于公平锁。 公平锁利用AQS的CLH队列,释放当前保持的锁 (读锁或者写锁) 时,优先为等待时间最长的那个写线程分配写入锁,当前前提是写线程的等待时间要比所有读线程的等待时间要长。同样一个线程持有写入锁或者有一个写线程已经在等待了,那么试图获取公平锁的 (非重入) 所有线程 (包括读写线程) 都将被阻塞,直到最先的写线程释放锁。如果读线程的等待时间比写线程的等待时间还有长,那么一旦上一个写线程释放锁,这一组读线程将获取锁。 重入性 读写锁允许读线程和写线程按照请求锁的顺序重新获取读取锁或者写入锁。当然了只有写线程释放了锁,读线程才能获取重入锁。 写线程获取写入锁后可以再次获取读取锁,但是读线程获取读取锁后却不能获取写入锁。 另外读写锁最多支持65535个递归写入锁和65535个递归读取锁。 锁降级 写线程获取写入锁后可以获取读取锁,然后释放写入锁,这样就从写入锁变成了读取锁,从而实现锁降级的特性。 锁升级 读取锁是不能直接升级为写入锁的。因为获取一个写入锁需要释放所有读取锁,所以如果有两个读取锁视图获取写入锁而都不释放读取锁时就会发生死锁。 锁获取中断 读取锁和写入锁都支持获取锁期间被中断。这个和独占锁一致。 条件变量 写入锁提供了条件变量(Condition)的支持,这个和独占锁一致,但是读取锁却不允许获取条件变量,将得到一个UnsupportedOperationException异常。 重入数 读取锁和写入锁的数量最大分别只能是65535 (包括重入数) 。 三、ReentrantReadWriteLock的内部实现 3.1 读写锁是独占锁的两个不同视图 ReentrantReadWriteLock里面的锁主体就是一个Sync,也就是上面提到的FairSync或者NonfairSync,所以说实际上只有一个锁,只是在获取读取锁和写入锁的方式上不一样,所以前面才有读写锁是独占锁的两个不同视图一说。 ReentrantReadWriteLock里面有两个类: ReadLock/WriteLock,这两个类都是Lock的实现。 // 清单1 ReadLock 片段 public static class ReadLock implements Lock, java.io.Serializable { private final Sync sync; protected ReadLock(ReentrantReadWriteLock lock) { sync = lock.sync; } public void lock() { sync.acquireShared(1); } public void lockInterruptibly() throws InterruptedException { sync.acquireSharedInterruptibly(1); } public boolean tryLock() { return sync.tryReadLock(); } public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout)); } public void unlock() { sync.releaseShared(1); } public Condition newCondition() { throw new UnsupportedOperationException(); } } //清单2 WriteLock 片段 public static class WriteLock implements Lock, java.io.Serializable { private final Sync sync; protected WriteLock(ReentrantReadWriteLock lock) { sync = lock.sync; } public void lock() { sync.acquire(1); } public void lockInterruptibly() throws InterruptedException { sync.acquireInterruptibly(1); } public boolean tryLock( ) { return sync.tryWriteLock(); } public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(timeout)); } public void unlock() { sync.release(1); } public Condition newCondition() { return sync.newCondition(); } public boolean isHeldByCurrentThread() { return sync.isHeldExclusively(); } public int getHoldCount() { return sync.getWriteHoldCount(); } } 清单1描述的是读锁的实现,清单2描述的是写锁的实现。显然WriteLock就是一个独占锁,这和ReentrantLock里面的实现几乎相同,都是使用了AQS的acquire/release操作。当然了在内部处理方式上与ReentrantLock还是有一点不同的。对比清单1和清单2可以看到,ReadLock获取的是共享锁,WriteLock获取的是独占锁。 ...

2013-07-13 · 4 min · 852 words · -

location.reload() 和 location.replace()

location.reload() 和 location.replace() 首先介绍两个方法的语法: 语法: location.reload([bForceGet]) 参数: bForceGet, 可选参数, 默认为 false,从客户端缓存里取当前页。 true, 则以 GET 方式,从服务端取最新的页面, 相当于客户端点击 F5(“刷新”) replace 方法,该方法通过指定URL替换当前缓存在历史里 (客户端) 的项目,因此当使用replace方法之后,你不能通过"前进"和"后退"来访问已经被替换的URL。 语法: location.replace(URL) 参数: URL 在实际应用的时候,重新刷新页面的时候,我们通常使用: location.reload() 或者是 history.go(0) 来做。因为这种做法就像是客户端点F5刷新页面,所以页面的method=“post"的时候,会出现"网页过期"的提示。那是因为Session的安全保护机制。可以想到: 当调用 location.reload() 方法的时候, aspx页面此时在服务端内存里已经存在, 因此必定是 IsPostback 的。如果有这种应用: 我们需要重新加载该页面,也就是说我们期望页面能够在服务端重新被创建, 我们期望是 Not IsPostback 的。这里,location.replace() 就可以完成此任务。被replace的页面每次都在服务端重新生成。你可以这么写: location.replace(location.href) http://blog.csdn.net/fangxinggood/article/details/604916

2013-07-12 · 1 min · 45 words · -

concat

concat 和其他数据库系统类似,Oracle字符串连接使用"||“进行字符串拼接,其使用方式和MSSQLServer中的加号”+“一样。 比如执行下面的SQL语句: SELECT ‘工号为’||FNumber||‘的员工姓名为’||FName FROM T_Employee WHERE FName IS NOT NULL 除了”||",Oracle还支持使用CONCAT()函数进行字符串拼接,比如执行下面的SQL语句: SELECT CONCAT(‘工号:’,FNumber) FROM T_Employee 如果CONCAT中连接的值不是字符串,Oracle会尝试将其转换为字符串,比如执行下面的SQL语句: SELECT CONCAT(‘年龄:’,FAge) FROM T_Employee 与MySQL的CONCAT()函数不同,Oracle的CONCAT()函数只支持两个参数,不支持两个以上字符串的拼接,比如下面的SQL语句在Oracle中是错误的: SELECT CONCAT(‘工号为’,FNumber,‘的员工姓名为’,FName) FROM T_Employee WHERE FName IS NOT NULL 运行以后Oracle会报出下面的错误信息: 参数个数无效 如果要进行多个字符串的拼接的话,可以使用多个CONCAT()函数嵌套使用,上面的SQL可以如下改写: SELECT CONCAT(CONCAT(CONCAT(‘工号为’,FNumber),‘的员工姓名为’),FName) FROM T_Employee WHERE FName IS NOT NULL

2013-07-11 · 1 min · 44 words · -

zigbee

zigbee ZigBee是一种低速短距离传输的无线网络协议。ZigBee协议从下到上分别为物理层(PHY)、媒体访问控制层(MAC)、传输层(TL)、网络层(NWK)、应用层(APL)等。其中物理层和媒体访问控制层遵循IEEE 802.15.4标准的规定。 ZigBee网络主要特点是低功耗、低成本、低速率、支持大量节点、支持多种网络拓扑、低复杂度、快速、可靠、安全。ZigBee网络中设备的可分为协调器(Coordinator)、汇聚节点(Router)、传感器节点(EndDevice)等三种角色。[1] 与此同时,中国物联网校企联盟认为: zigbee作为一种短距离无线通信技术,由于其网络可以便捷的为用户提供无线数据传输功能,因此在物联网领域具有非常强的可应用性。 Zigbee是基于IEEE802.15.4标准的低功耗个域网协议。根据这个协议规定的技术是一种短距离、低功耗的无线通信技术。这一名称来源于蜜蜂的八字舞,由于蜜蜂(bee)是靠飞翔和"嗡嗡"(zig)地抖动翅膀的"舞蹈"来与同伴传递花粉所在方位信息,也就是说蜜蜂依靠这样的方式构成了群体中的通信网络。其特点是近距离、低复杂度、自组织、低功耗、低数据速率、低成本。主要适合用于自动控制和远程控制领域,可以嵌入各种设备。简而言之,ZigBee就是一种便宜的,低功耗的近距离无线组网通讯技术。 ZigBee译为"紫蜂",它与蓝牙相类似。是一种新兴的短距离无线通信技术,用于传感控制应用(Sensor and Control)。由IEEE 802.15工作组中提出,并由其TG4工作组制定规范。 2001年8月,ZigBee Alliance成立。 2004年,ZigBee V1.0诞生。它是Zigbee规范的第一个版本。由于推出仓促,存在一些错误。 2006年,推出ZigBee 2006,比较完善。 2007年底,ZigBee PRO推出。 2009年3月,Zigbee RF4CE推出,具备更强的灵活性和远程控制能力。 2009年开始,Zigbee采用了IETF的IPv6 6Lowpan标准作为新一代智能电网Smart Energy(SEP 2.0)的标准,致力于形成全球统一的易于与互联网集成的网络,实现端到端的网络通信。随着美国及全球智能电网的建设,Zigbee将逐渐被IPv6/6Lowpan标准所取代。 ZigBee的底层技术基于IEEE 802.15.4,即其物理层和媒体访问控制层直接使用了IEEE 802.15.4的定义。 在蓝牙技术的使用过程中,人们发现蓝牙技术尽管有许多优点,但仍存在许多缺陷。对工业,家庭自动化控制和工业遥测遥控领域而言,蓝牙技术太复杂,功耗大,距离近,组网规模太小等。而工业自动化,对无线数据通信的需求越来越强烈,而且,对于工业现场,这种无线传输必须是高可靠的,并能抵抗工业现场的各种电磁干扰。因此,经过人们长期努力,ZigBee协议在2003年正式问世。另外,Zigbee使用了在它之前所研究过的面向家庭网络的通信协议Home RF Lite。 长期以来,低价位、低速率、短距离、低功率的无线通讯市场一直存在着。蓝牙的出现,曾让工业控制、家用自动控制、玩具制造商等业者雀跃不已, 但是蓝牙的售价一直居高不下,严重影响了这些厂商的使用意愿。如今,这些业者都参加了IEEE802.15.4小组,负责制定ZigBee的物理层和媒体介质访问层。IEEE802.15.4规范是一种经济、高效、低数据速率(<250kbps)、工作在2.4GHz和868/915MHz的无线技术,用于个人区域网和对等网络。它是ZigBee应用层和网络层协议的基础。ZigBee是一种新兴的近距离、低复杂度、低功耗、低数据速率、低成本的无线网络技术,它是一种介于无线标记技术和蓝牙之间的技术提案。主要用于近距离无线连接。它依据802.15.4标准,在数千个微小的传感器之间相互协调实现通信。这些传感器只需要很少的能量,以接力的方式通过无线电波将数据从一个网络节点传到另一个节点,所以它们的通信效率非常高。 ①低功耗。在低耗电待机模式下,2节5号干电池可支持1个节点工作6~24个月,甚至更长。这是ZigBee的突出优势。相比较, 蓝牙能工作数周、WiFi可工作数小时。 TI公司和德国的Micropelt公司共同推出新能源的ZigBee节点。该节点采用Micropelt公司的热电发电机给TI公司的ZigBee提供电源。 ②低成本。通过大幅简化协议(不到蓝牙的1/10),降低了对通信控制器的要求,按预测分析,以8051的8位微控制器测算,全功能的主节点需要32KB代码,子功能节点少至4KB代码,而且ZigBee免协议专利费。每块芯片的价格大约为2美元。 ③低速率。ZigBee工作在20~250kbps的速率,分别提供250 kbps(2.4GHz)、40kbps(915 MHz)和20kbps(868 MHz)的原始数据吞吐率,满足低速率传输数据的应用需求。 ④近距离。传输范围一般介于10~100m之间,在增加发射功率后,亦可增加到1~3km。这指的是相邻节点间的距离。如果通过路由和节点间通信的接力,传输距离将可以更远。 ⑤短时延。ZigBee的响应速度较快,一般从睡眠转入工作状态只需15ms,节点连接进入网络只需30ms,进一步节省了电能。相比较,蓝牙需要3~10s、WiFi 需要3 s。 ⑥高容量。ZigBee可采用星状、片状和网状网络结构,由一个主节点管理若干子节点,最多一个主节点可管理254个子节点;同时主节点还可由上一层网络节点管理,最多可组成65000 个节点的大网。 ⑦高安全。ZigBee提供了三级安全模式,包括无安全设定、使用访问控制清单(Access Control List, ACL) 防止非法获取数据以及采用高级加密标准(AES 128)的对称密码,以灵活确定其安全属性。 ⑧免执照频段。使用工业科学医疗(ISM)频段,915MHz(美国), 868MHz(欧洲), 2. 4GHz(全球) , 。 由于此三个频带物理层并不相同,其各自信道带宽也不同,分别为0.6MHz, 2MHz和5MHz。分别有1个, 10个和16个信道。 这三个频带的扩频和调制方式亦有区别。扩频都使用直接序列扩频(DSSS),但从比特到码片的变换差别较大。调制方式都用了调相技术,但868MHz和915MHz频段采用的是BPSK,而2.4GHz频段采用的是OQPSK。 在发射功率为0dBm的情况下,蓝牙通常能有10米的作用范围。而ZigBee在室内通常能达到30-50米的作用距离,在室外空旷地带甚至可以达到400米(TI CC2530不加功率放大)。 所以ZigBee可归为低速率的短距离无线通信技术。 无线数据传输 简单的说,ZigBee是一种高可靠的无线数传网络,类似于CDMA和GSM网络。ZigBee数传模块类似于移动网络基站。通讯距离从标准的75m到几百米、几公里,并且支持无限扩展。 ZigBee是一个由可多到65000个无线数传模块组成的一个无线数传网络平台,在整个网络范围内,每一个ZigBee网络数传模块之间可以相互通信,每个网络节点间的距离可以从标准的75m无限扩展。 与移动通信的CDMA网或GSM网不同的是,ZigBee网络主要是为工业现场自动化控制数据传输而建立,因而,它必须具有简单,使用方便,工作可靠,价格低的特点。而移动通信网主要是为语音通信而建立,每个基站价值一般都在百万元人民币以上,而每个ZigBee"基站"却不到1000元人民币。每个ZigBee网络节点不仅本身可以作为监控对象,例如其所连接的传感器直接进行数据采集和监控,还可以自动中转别的网络节点传过来的数据资料。除此之外,每一个Zigbee网络节点(FFD)还可在自己信号覆盖的范围内,和多个不承担网络信息中转任务的孤立的子节点(RFD)无线连接。 互联网标准化组织IETF也看到了无线传感器网络 (或者物联网) 的广泛应用前景,也加入到相应的标准化制定中。以前许多标准化组织和研究者认为IP技术过于复杂,不适合低功耗、资源受限的无线传感器网络,因此都是采用非IP技术。在实际应用中,如zigbee需要接入互联网时需要复杂的应用层网关,也不能实现端到端的数据传输和控制。与此同时,与zigbee类似的标准还有z-wave、ANT、Enocean等,相互之间不兼容,不利于产业化的发展。IETF和许多研究者发现了存在的这些问题,尤其是基于开源的 uIP 协议实现了轻量级的 IPv6 协议,证明了 IPv6 不仅可以运行在低功耗资源受限的设备上,而且,比 zigbee 更加简单,彻底改变了大家的偏见,之后基于 IPv6 的无线传感器网络技术得到了迅速发展。 IETF 已经完成了核心的标准规范,包括 IPv6 数据报文和帧头压缩规范 6Lowpan、 面向低功耗、低速率、链路动态变化的无线网络路由协议 RPL[3]、以及面向无线传感器网络应用的应用层标准CoAP[4],相关的标准规范已经发布[5]。IETF组织成立了IPSO联盟,推动该标准的应用,并发布了一些列白皮书[6]。 IPv6/6Lowpan已经成为许多其它标准的核心,包括智能电网Zigbee SEP2.0、工业控制标准ISA100.11a、有源RFID ISO1800-7.4 (DASH) 等。IPv6/6Lowpan具有诸多优势: 可以运行在多种介质上,如低功耗无线、电力线载波、WiFi和以太网,有利于实现统一通信;IPv6可以实现端到端的通信,无需网关,降低成本; 6Lowpan中采用RPL路由协议,路由器可以休眠,也可以采用电池供电,应用范围广,而zigbee技术路由器不能休眠,应用领域受到限制。6Lowpan标准已经得到大量开源软件实现,最著名的是Contiki[7]、TinyOS系统,已经实现完整的协议栈,全部开源,完全免费,已经在许多产品中得到应用。IPv6/6Lowpan协议将随着无线传感器网络以及物联网的广泛应用,很可能成为该领域的事实标准。

2013-07-10 · 1 min · 97 words · -

IDENTITY COLUMN

IDENTITY COLUMN 一、标识列的定义以及特点 SQL Server中的标识列又称标识符列,习惯上又叫自增列。 该种列具有以下三种特点: 列的数据类型为不带小数的数值类型 在进行插入(Insert)操作时,该列的值是由系统按一定规律生成,不允许空值 列值不重复,具有标识表中每一行的作用,每个表只能有一个标识列。 由于以上特点,使得标识列在数据库的设计中得到广泛的使用。 二、标识列的组成 创建一个标识列,通常要指定三个内容: 类型 (type) 在SQL Server 2000中,标识列类型必须是数值类型,如下: decimal、int、numeric、smallint、bigint 、tinyint 其中要注意的是,当选择decimal和numeric时,小数位数必须为零 另外还要注意每种数据类型所有表示的数值范围 种子(seed) 是指派给表中第一行的值,默认为1 递增量(increment) 相邻两个标识值之间的增量,默认为1。 三、标识列的创建与修改 标识列的创建与修改,通常在企业管理器和用Transact-SQL语句都可实现,使用企业管理管理器比较简单,请参考SQL Server的联机帮助,这 里只讨论使用Transact-SQL的方法 创建表时指定标识列 标识列可用 IDENTITY 属性建立,因此在SQL Server中,又称标识列为具有IDENTITY属性的列或IDENTITY列。 下面的例子创建一个包含名为ID,类型为int,种子为1,递增量为1的标识列 CREATE TABLE T_test (ID int IDENTITY(1,1), Name varchar(50) ) 在现有表中添加标识列 下面的例子向表T_test中添加一个名为ID,类型为int,种子为1,递增量为1的标识列 -创建表 CREATE TABLE T_test (Name varchar(50) ) -插入数据 INSERT T_test(Name) VALUES(‘张三’) -增加标识列 ALTER TABLE T_test ADD ID int IDENTITY(1,1) 判段一个表是否具有标识列 可以使用 OBJECTPROPERTY 函数确定一个表是否具有 IDENTITY (标识) 列,用法: ...

2013-07-10 · 1 min · 155 words · -

Nginx config, 配置, nginx.conf

Nginx config, 配置, nginx.conf nginx 配置文件结构 Global: nginx 运行相关 Events: 与用户的网络连接相关 http http Global: 代理,缓存,日志,以及第三方模块的配置 server server Global: 虚拟主机相关 location: 地址定向,数据缓存,应答控制,以及第三方模块的配置 worker_processes, nginx 进程数,建议设置为等于 CPU 总核心数 worker_processes 8; worker_connections 每一个 worker 进程能并发处理 (发起) 的最大连接数 (包含所有连接数). 总连接数 = worker_processes * worker_connections events { worker_connections 20480; multi_accept on; use epoll; } max_clients = worker_processes * worker_connections; multi_accept multi_accept 告诉 nginx 收到一个新连接通知后接受尽可能多的连接。 multi_accept 可以让 nginx worker 进程尽可能多地接受请求。它的作用是让 worker 进程一次性地接受监听队列里的所有请求,然后处理。如果 multi_accept 的值设为off,那么 worker 进程必须一个一个地接受监听队列里的请求。 ...

2013-07-09 · 8 min · 1556 words · -

golang 控制语句 if, for, switch

golang 控制语句 if, for, switch http://www.cnblogs.com/howDo/archive/2013/06/01/GoLang-Control.html Go中的控制语句较精简,仅有 if, for, select 和 switch. 但使用时均比较灵活 if 在Go中条件语句 if 中如果条件部分的计算结果为 true 时将执行语句块,否则则执行else语句块(如果存在else时),此逻辑和其他语言中的if一样,但是在Go中还是有一些不同之处。 if 条件表达式不能使用括号 () 包含 if 语句代码片段必须使用 {}, 并且左括号必须和 if 在同一行 if 条件表达式的前面可以包含初始化语句, 支持平行赋值, 但不支持多个赋值语句 赋值 + 条件判断 if a, b := 21, 3; a > b { fmt.Println("a>b ? true") } 在if条件表达式前面声明的的变量只能在if-else语句块中使用。 if a, b := 21, 31; a > b { fmt.Println("a>b ? true") }else { fmt.Println(a,b) //Ok } fmt.Println(a,b) //error: undefined a ,undefined b 还需要注意的是如果在if-else 中包含return 时,编译器无法解析出else中的retrun,导致方法缺少return ,目前1.1版本已支持该方式。 ...

2013-07-09 · 3 min · 597 words · -

Cloc, 代码统计工具

Cloc, 代码统计工具 Cloc是一款使用Perl语言开发的开源代码统计工具,支持多平台使用、多语言识别,能够计算指定目标文件或文件夹中的文件数(files)、空白行数(blank)、注释行数(comment)和代码行数(code)。 pacman -S cloc cloc ~/projects/wiloon.com/ https://linux.cn/article-10118-1.html

2013-07-08 · 1 min · 9 words · -

LEAD TIME

LEAD TIME LEAD TIME是完成一项活动所需要的时间。这种活动通常指物料和产品的获得,无论是从外面购入的还是用自己的设备制造的。提前期可由下列各种时间或它们的总和组成: 订单准备时间、排队时间、加工时间、搬运时间或运输时间、接收和检测时间 前置时间 (Lead Time) ,也称前置期、备货周期 前置时间 (Lead time) 是供应链管理中的一个术语,是指从采购方开始下单订购到供应商交货所间隔的时间,通常以天数或小时计算。 减少前置时间可以使生产商和零售商平均库存水平得到减少,而且前置时间的减少可以使零售商订货模型更加稳定,也会给生产商的生产决策来带很大好处,能保证处于同一条供应链上的生产商和零售商实现双赢。 参考文献: http://wiki.mbalib.com/wiki/%E5%89%8D%E7%BD%AE%E6%97%B6%E9%97%B4

2013-07-02 · 1 min · 16 words · -

持续集成与测试自动化, CI, CD

持续集成与测试自动化, CI, CD CI, CD AND CD CI很容易理解,就是持续集成。但是CD既可以指代码持续交付,也可理解为代码持续部署。CI和CD之间有很多相似的部分,但是也有很大的区别。 持续集成 (CONTINUOUS INTEGRATION) 在持续集成环境中,开发人员将会频繁的提交代码到主干。这些新提交在最终合并到主线之前,都需要通过编译和自动化测试流进行验证。这样做是基于之前持续集成过程中很重视自动化测试验证结果,以保障所有的提交在合并主线之后的质量问题,对可能出现的一些问题进行预警。 持续交付 (CONTINUOUS DELIVERY) 持续交付就是讲我们的应用发布出去的过程。这个过程可以确保我们尽可能快的实现交付。这就意味着除了自动化测试,我们还需要有自动化的发布流,以及通过一个按键就可以随时随地实现应用的部署上线。 通过持续交付,您可以决定每天,每周,每两周发布一次,这完全可以根据自己的业务进行设置。 但是,如果您真的希望体验持续交付的优势,就需要先进行小批量发布,尽快部署到生产线,以便在出现问题时方便进行故障排除。 持续部署 (CONTINUOUS DEPLOYMENT) 如果我们想更加深入一步的话,就是持续部署了。通过这个方式,任何修改通过了所有已有的工作流就会直接和客户见面。没有人为干预 (没有一键部署按钮) ,只有当一个修改在工作流中构建失败才能阻止它部署到产品线。 持续部署是一个很优秀的方式,可以加速与客户的反馈循环,但是会给团队带来压力,因为不再有“发布日”了。开发人员可以专注于构建软件,他们看到他们的修改在他们完成工作后几分钟就上线了。基本上,当开发人员在主分支中合并一个提交时,这个分支将被构建、测试,如果一切顺利,则部署到生产环境中。 我从毕业到现在, 曾在大小不同的三个公司就职: 有民营的、有外资的、也有上市公司。 但以前大多都是做项目,从事软件开发工作,绝大部分公司对测试都不重视,即使有也没有成规模, 更谈不上建立测试体系。总之,重开发轻测试的管理思想在中国延续了几十年、并且还要继续,看看他们给测试工程师开的低工资和老师在课堂上讲到测试时一笔带过就知道测试被中国的老板所忽略。 最近两年,我从事CRM软件产品的测试、项目管理工作。 由于公司对软件的质量要求特别高, 这必然引起了大家对测试工作的重视,不但要求有强大的测试团队,该团队必须具备在业务方面、测试技能方面的专业水平, 而且在软件开发过程方面经常由于测试而作持续不断地调整。 幸运的是,随着软件开发技术和工具的提高,软件工程和软件过程实践的推广, 软件测试日益得到重视和专业化。 我从事测试工作期间,一直研究CMM、测试理论、自动化测试工具,并建立了一套完整的测试体系。 在此并不介绍整个测试体系,而是介绍测试方面最值得探讨的部分: 持续集成与测试自动化。目的是与大家共同进步。当然已经有很多关于持续集成和自动化测试方面的介绍,但我要介绍的不只是持续集成,也不只是自动化测试,而是测试如何的自动化. 二、测试自动化 自动化测试就是希望能够通过自动化测试工具或其他手段,按照测试工程师的预定计划进行自动的测试,目的是减轻手工测试的劳动量,从而达到提高软件质量的目的。自动化测试的目的在于发现老缺陷。而手工测试的目的在于发现新缺陷。 测试自动化涉及到测试流程、测试体系、自动化化编译、持续集成、自动发布测试系统以及自动化测试等方面整合。也就是说要让测试能够自动化,不仅是技术、工具的问题,更是一个公司和组织的文化问题。首先公司从资金、管理上支持您,其次要有专门的测试团队去建立适合自动化测试的测试流程、测试体系;其次就是把原代码从受控库中取出、编译、集成、发布可运行系统、进行自动化的单元测试和自动化的功能测试的过程。 (一) 、自动化测试的好处 对新版本执行回归测试--测试每个特征 对于产品型的软件,每发布一个新的版本,其中大部分功能和界面都和上一个版本相似或完全相同,这部分功能特别适合于自动化测试, 从而可以让测试达到测试每个特征的目的。 更多更频繁的测试--沉闷、耗时 我们的产品向市场的发布周期是3个月,也就是我们的开发周期只有短短的3个月,而在测试期间是每天/每2天都要发布一个版本供测试人员测试,一个系统的功能点有几千个上万个,人工测试是非常的耗时和繁琐,这样必然会使测试效率低下。 替代手工测试的困难--300个用户有些非功能性方面的测试: 压力测试、并发测试、大数据量测试、崩溃性测试,用人来测试是不可能达到的。 在没有引入自动化测试工具之前,为了测试并发,研发中心的一、两百号人在研发经理的口令: 1-、2-、3!, 大家同时按下同一个按钮。回想起这中情景也蛮有意思的。 具有一致性和可重复性 由于每次自动化测试运行的脚本是相同的, 所以每次执行的测试具有一致性, 人是很难做到的. 由于自动化测试的一致性,很容易发现被测软件的任何改变。 更好的利用资源--周未/晚上 理想的自动化测试能够按计划完全自动的运行, 在开发人员和测试人员不可能实行三班倒的情况下, 自动化测试可以胜任这个任务, 完全可以在周末和晚上执行测试. 这样充分的利用了公司的资源,也避免了开发和测试之间的等待. 解决测试与开发之间的矛盾 通常在开发的末期,进入集成测试阶段, 由于每发布一个版本的初期,测试系统的错误比较少,这时开发人员有等待测试人员测试出错误的时间. 事实上在叠代周期很短的开发模式中,存在更多的矛盾, 但自动化测试可以解决其中的主要矛盾。 ...

2013-06-30 · 1 min · 148 words · -

ADX指标

ADX指标 中文全称: 平均趋向指数 英文全称: Average Directional Index 或者Average Directional Movement Index 平均动向指标Average Directional Index, ADX 趋势分析指标的共同缺陷是适用于趋势市场状况,而不适用于震荡市场状况,ADX的发明旨在克服这一问题。ADX, Average Directional Index是由技术分析大师Welles Wilder发明的,他同时也是相对强弱指数RSI和抛物线止损反转指标Parabolic SAR的发明者。 国外投资者经常使用ADX指标,国内用的反而比较少,不过在编写交易系统时,经常用到ADX或者ATR指标判断盘整、振荡和单边趋势。 1.ADX指数是反映趋向变动的程度,而不是方向的本身。 2.进场与出场是采用+DI14与-DI14的穿越信号。 3.当极端点交易法则生效时,法则2将有例外。当DI发生穿越信号时,取当天的极端点做为止损点;换言之,多头头寸取当天的低价为止损点,空头头寸取当天的高价。在随后的几之内,如果止损点未被触及,即使DI再发生穿越信号也不需理会。 4.当ADX的位置高于两条DI而方向发生改变,这是趋势反转的早期信号,可以做部份的获利了结。最后的平仓信号是来自于DI穿越或极端点的止损被引发。当ADX改变方向时,如果+DI14高于-DI14,这代表趋势的变动是由上亦下,反之亦然。 5.如果ADX高于两条DI,而且读数明显偏高,这代表既有的趋势已经持续一段时间。这并不是建立新头寸的理想时机,因场信号很可能反复。换言之,ADX的读数偏高,相当于是超买/超卖,顺势的新交易头寸通常很难获利。 6.如果ADX同时低于两条DI,避免采用顺势交易的系统,因为市场中没有明显的趋势。 7.如果ADX的读数低于20~25,不论它与两条DI的相对位置如何,都避免采用顺势交易的系统,因为市场中没有明显的趋势 8.例: 在ADX为黄线,+DI为红线,-DI为绿线的前提下: 红线上行,绿线下行,且黄线与上行线同行,则价格上涨;如果绿线上行,红线下行,且黄线与上行线同行,则价格下跌。 9.通常情况下可以简单理解为: ADX线代表力量的强弱,+DI和-DI谁占优势随着力量一起上扬,那么就代表走势向哪个方向发展。 平均趋向指标ADX是另一种常用的趋势衡量指标。 ADX 无法告诉你趋势的发展方向。可是,如果趋势存在, ADX 可以衡量趋势的强度。不论上升趋势或下降趋势, ADX 看起来都一样。 ADX 的读数越大,趋势越明显。衡量趋 势强度时,需要比较几天的 ADX 读数,观察 ADX 究竟是上升或下降。 ADX 读数上升,代表趋势转强;如果 ADX 读数下降,意味着趋势转弱。当 ADx 曲线向上攀升,趋势越来越强,应该会持续发展。如果 ADX 曲线下滑,代表趋势开始转弱,反转的可能性增加。单就 ADX 本身来说,由于指标落后价格走势,所以算不上是很好的指标,不适合单就 ADX 进行操作。可是,如果与其他指标配合运用, ADX 可以确认市场是否存在趋势,并衡量趋势的强度。

2013-06-28 · 1 min · 62 words · -

number integer

number integer 建表的时候,如果是浮点数,一般设置为 number(m,n )[m为精度,n为小数位数,所以整数为m-n位], 整数设置为integer; 比如: create table abc ( a number(38,0), b number(38) c integer, d number ) 那么a,b,c,d 分别有什么区别呢? a,b其实是一样的,都是38位的范围; c是不是和a,b一样呢?测试后是不一样的,c的最大值可以达到9e125,显然远远地大于38位的范围; d和a,b,c有什么区别呢,首先d可以放小数,另外它的范围同样远远大于38位; 具体这a,b,c,d四种类型的明确差异,我也说不清楚,希望有专家把它解释清楚,我这里只是抛砖引玉。 以前我一直以为 integer=number(38,0) -38是number的最大精度 刚才无意中发现integer 是个超大的数据类型,最大可以表示为power(10,126)-1 也就是说这么大的数字,大概需要多少个字节呢, 因为一个字节最大表示256,那么N个字节最大表示power(256,n)>=power(10,126) 现在求这个N: 解法是: select LOG(256,10)*126 from dual 求得的解是 53, 也就是说,一个integer类型最少使用53个字节。 所以我觉得Integer类型还是尽量少用,一般很少用到这么大的数字; 特别是某些人对于boolean类型的处理; 因为Oracle的表结构中没有布尔类型,所以很多人干脆用integer 代替布尔类型,这个感觉有点"奢侈"; 我一般都用char(1) 表示布尔型;‘0’表示false,‘1’表示true 另外,比如varchar2(200)这个类型,它是动态分配的,所以字符串按实际使用的占用空间,但是integer却是固定暂用了最少53个字节,所以大部分时候,integer 类型还是不用为妙; 就算在pl/sql 里; 定义变量的时候,也不要使用integer; 可以用binary_integer 或pls_integer ;11g里还出了个新的整形,效率更高,叫simple_integer,反正最好不用integer就是了。 效率测试下来: simple_integer>pls_integer>binary_integer>integer; SIMPLE_INTEGER Subtype of PLS_INTEGER SIMPLE_INTEGER is a predefined subtype of the PLS_INTEGER data type that has the same range as PLS_INTEGER and has a NOT NULL constraint (explained in“NOT NULL Constraint”). It differs significantly from PLS_INTEGER in its overflow semantics. ...

2013-06-28 · 1 min · 138 words · -

关于数据驱动和关键字驱动的理解整理

关于数据驱动和关键字驱动的理解整理 关于数据驱动,以下这篇帖子还是给了很大的启发: http://bbs.51testing.com/viewthread.php?tid=113729&extra=&highlight=%CA%FD%BE%DD%C7%FD%B6%AF&page=1 摘录一些精妙的论点: 51testing论坛的phililschen: “什么是数据驱动呢?很大一部分人肯定认为数据驱动就是把需要参数化的东西写在EXCEL里,然后在跑脚本时调用。如果我告诉你,这其实不是数据驱动,而只是较高级的参数化,你肯定会很惊讶!现在我来解释一下: 首先为什么叫数据驱动呢,那么它肯定有驱动的含义,比如你用EXCEL可以控制测试的业务流吗?回答是不能的。那又如何作到驱动呢?所以说我们将测试数据放在独立的文件里只是高级的参数话。而数据驱动,你必须有数据来控制测试的业务流。比如你测一个WEB程序,有很多页面,你可以通过一个数据来控制每次是再哪个页面下工作的 (即通过数据来导航到相应的页面) 。它是关键字驱动的低级版本,他控制的是函数级的,而关键字是控制动作级的。所以数据驱动应该是可以控制整个测试的” 51testing论坛的dreamever: “数据驱动本身不是一个工业级标准的概念,因此在不同的公司,都会有好几个解释版本。首先我同意楼主的关于数据驱动的观点,也就是说如果我们仅仅是把测试数据放在数据文件里,这只是一种比较高级的参数化而已。其实我更倾向于把数据驱动理解为一种模式或者一种思想 对于数据驱动的讨论,我们不妨先抛开QTP来进行。无论是进行自动化测试还是手工测试时,我们都需要设计测试用例,准备测试数据,并且把测试用例与数据分开,在一套测试用例上运行多套测试数据是比较有效率的。我相信这一点大家应该都认同吧。 那么我们不妨再看一下手工测试的场景: 当一个手工测试人员A发现在测试数据存储目录下多了一套测试数据时,他就会意识到应该马上执行测试用例,并输入这套新的测试数据。其实是测试数据的变化触发了A的测试行为。 (有人可能说了我们公司不是这么做的,注意,我们不是在讨论实际的测试管理,我们在对测试模型进行抽象) 。如果我们更抽象一下,可以这样来看: 当测试数据变化时,测试用例就会被执行 (无论是A主动还是leader打电话通知) ,并且按照预先定义的规则去读取测试数据并执行测试用例。那么这种情况我们是不是可以理解为一种数据驱动呢?也就是说只要有了新的测试数据或者测试数据发生了变化,那么A就会去执行测试用例。这一过程的目的就是为了让所有的测试数据都得到输入并返回相应的输出结果。 如果大家同意上面的情景是一种数据驱动测试的例子,那么我们可以对自动化测试中的数据驱动进行同样的解释: 由机器自动读取测试数据,然后测试用具运行测试脚本执行测试用例,并按照预先设置好的参数化字段读取测试数据,返回测试结果。目的就是使所有的测试数据都得到输入,并返回输出,验证数据的输入和输出是否符合预期值。这里的测试数据不仅包括业务数据,还包括一些动作关键字或决策关键字,以提供足够的信息,让测试工具知道该调用什么样的脚本,应该如何处理各种情况。相对于不同的测试工具,其表现形式有可能不同,QTP提供了关键字视图和数据表,robot提出了决策表的概念,Watir的话本身没有什么特殊的模式,完全看测试人员把框架设计成什么样了。其实本质上都是消息驱动的不同表现而已,例如刚才的手工测试的例子,测试数据发生变化我们可以把它看成一种消息,接收到这个消息A就开始执行测试。” 51testing论坛的jackmail: “数据驱动中的 driven 一词,你可以简单的理解成导向,导向什么?结果。就是测试数据决定了测试结果,这就是所谓数据驱动,QTP实现了数据驱动的功能,模型,feature,特征,无非是个词汇而已,怎么说都没问题,用QTP你可以简单的完成你想实现的数据驱动方法的测试,他就是实现了xx功能。 还有关键字驱动,就是 关键字决定了结果。 在QTP里关键字就是step中的测试对象名称 (对象方法属性,或者值 (测试数据) ) 。测试对象名称的改变,就决定了结果的变更。以前有些人写的所谓框架是把对象从Excel表格中导入导出的,他们实现的就是关键字驱动。 什么驱动,就是什么决定结果。本来结果是固定的,由于驱动数据的变更,导致了结果的不同,没那么复杂。其实概念都是人定的,少去钻牛角尖,理解个大概意思就行了。” 最后引用一下一篇关键字驱动的理解的文章,毕竟这是QTP主推的东西 最初用QTP就是简单的录制,然后修改脚本,缺点如下: 应用软件必须具备一定的稳定性,并且在整个业务流程上都必须完整的实现了,否则顺序录制整能实现? 自动化脚本的维护性成本非常的高 自动化脚本的可重用性比较差 随之出现了关键字驱动的概念,一切都以对象为出发点,这有点像编程语言中从过程化向面向对象转化,在QTP中的具体实现方法是: 在单个程序界面上将测试所涉及到的对象手工添加到对象库中 在专家视图中基于对象库中的对象编写自动化测试脚本 以上这样做的明显的优点在于: 脚本的可控性非常的强,模块化组织也比较好 可以在开发完全实现所有的业务流程功能前就建立测试脚本,占据了比较大的主动性,为时间上的安排提供了更大的空间,一个词概括: “测试先行”

2013-06-27 · 1 min · 45 words · -

GC日志

GC日志 本文是 Plumbr 发行的 Java垃圾收集指南 的部分内容。文中将介绍GC日志的输出格式, 以及如何解读GC日志, 从中提取有用的信息。我们通过 -XX:+UseSerialGC 选项,指定JVM使用串行垃圾收集器, 并使用下面的启动参数让 JVM 打印出详细的GC日志: -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps 这样配置以后,发生GC时输出的日志就类似于下面这种格式(为了显示方便,已手工折行): 2015-05-26T14:45:37.987-0200: 151.126: [GC (Allocation Failure) 151.126: [DefNew: 629119K->69888K(629120K), 0.0584157 secs] 1619346K->1273247K(2027264K), 0.0585007 secs] [Times: user=0.06 sys=0.00, real=0.06 secs] 2015-05-26T14:45:59.690-0200: 172.829: [GC (Allocation Failure) 172.829: [DefNew: 629120K->629120K(629120K), 0.0000372 secs] 172.829: [Tenured: 1203359K->755802K(1398144K), 0.1855567 secs] 1832479K->755802K(2027264K), [Metaspace: 6741K->6741K(1056768K)], 0.1856954 secs] [Times: user=0.18 sys=0.00, real=0.18 secs] 上面的GC日志暴露了JVM中的一些信息。事实上,这个日志片段中发生了 2 次垃圾回收事件(Garbage Collection events)。其中一次清理的是年轻代(Young generation), 而第二次处理的是整个堆内存。下面我们来看,如何解读第一次GC事件,发生在年轻代中的小型GC(Minor GC): 2015-05-26T14:45:37.987-02001:151.1262:[GC3(Allocation Failure4) ...

2013-06-27 · 2 min · 283 words · -

subsonic 调用 存储过程

subsonic 调用 存储过程 [csharp] public static int GetRUID(string tblName) { StoredProcedure spd = new StoredProcedure(“GenerateRUID”); spd.Command.AddParameter("@tblName", tblName); spd.Command.AddOutputParameter("@currentnumber"); spd.Execute(); int currentnumber = int.Parse(spd.OutputValues[0].ToString()); return currentnumber; } [/csharp]

2013-06-27 · 1 min · 27 words · -

java 代码块

java 代码块 在编程过程中我们可能会遇到如下这种形式的程序: public class Test { { //... } } 这种形式的程序段我们将其称之为代码块,所谓代码块就是用大括号({})将多行代码封装在一起,形成一个独立的数据体,用于实现特定的算法。一般来说代码块是不能单独运行的,它必须要有运行主体。在Java中代码块主要分为四种: 一、 普通代码块 普通代码块是我们用得最多的也是最普遍的,它就是在方法名后面用{}括起来的代码片段。普通代码块是不能够单独存在的,它必须要紧跟在方法名后面。同时也必须要使用方法名调用它。 public class Test { public void test(){ System.out.println(“普通代码块”); } } 二、 静态代码块 想到静态我们就会想到static,静态代码块就是用static修饰的用{}括起来的代码片段,它的主要目的就是对静态属性进行初始化。 public class Test { static{ System.out.println(“静态代码块”); } } 三、 同步代码块 使用 synchronized 关键字修饰,并使用"{}"括起来的代码片段,它表示同一时间只能有一个线程进入到该方法块中,是一种多线程保护机制。 四、 构造代码块 在类中直接定义没有任何修饰符、前缀、后缀的代码块即为构造代码块。我们明白一个类必须至少有一个构造函数,构造函数在生成对象时被调用。构造代码块和构造函数一样同样是在生成一个对象时被调用,那么构造代码在什么时候被调用?如何调用的呢?看如下代码: 复制代码 public class Test { /** 构造代码 */ { System.out.println(“执行构造代码块…”); } /** * 无参构造函数 */ public Test(){ System.out.println("执行无参构造函数..."); } /** * 有参构造函数 * @param id id */ public Test(String id){ System.out.println("执行有参构造函数..."); } } ...

2013-06-27 · 2 min · 215 words · -

符号引用 直接引用

符号引用 直接引用 符号引用(Symbolic References), 直接引用 https://blog.csdn.net/u014296316/article/details/83066436 https://www.zhihu.com/question/30300585 http://blog.csdn.net/imzoer/article/details/8086255 JVM在装载class文件的时候,会有一步是将符号引用解析为直接引用的过程。 那么这里的直接引用到底是什么呢? 对于指向"类型"【Class对象】、类变量、类方法的直接引用可能是指向方法区的本地指针。 指向实例变量、实例方法的直接引用都是偏移量。实例变量的直接引用可能是从对象的映像开始算起到这个实例变量位置的偏移量。实例方法的直接引用可能是方法表的偏移量。 在《深入Java虚拟机》书的第197页我们可以看到,子类中方法表的偏移量和父类中的方法表的偏移量是一致的。比如说父类中有一个say()方法的偏移量是7,那么子类中say方法的偏移量也是7。 书中第199页说,通过"接口引用"来调用一个方法,jvm必须搜索对象的类的方法表才能找到一个合适的方法。这是因为实现同一个接口的这些类中,不一定所有的接口中的方法在类方法区中的偏移量都是一样的。他们有可能会不一样。这样的话可能就要搜索方法表才能确认要调用的方法在哪里。 而通过"类引用"来调用一个方法的时候,直接通过偏移量就可以找到要调用的方法的位置了。【因为子类中的方法的偏移量跟父类中的偏移量是一致的】 所以,通过接口引用调用方法会比类引用慢一些。 下面介绍下什么是接口引用。 interface A{void say();} class B implements A{} class C{public static void main(String []s){A a=new B();a.say()}} 在上面的第三行代码中,就是用"接口引用"来调用方法。 符号引用: 符号引用是一个字符串,它给出了被引用的内容的名字并且可能会包含一些其他关于这个被引用项的信息——这些信息必须足以唯一的识别一个类、字段、方法。这样,对于其他类的符号引用必须给出类的全名。对于其他类的字段,必须给出类名、字段名以及字段描述符。对于其他类的方法的引用必须给出类名、方法名以及方法的描述符。

2013-06-24 · 1 min · 35 words · -

gorm

gorm db.Table("go_service_info").Select("go_service_info.serviceId as service_id, go_service_info.serviceName as service_name, go_system_info.systemId as system_id, go_system_info.systemName as system_name").Joins("left join go_system_info on go_service_info.systemId = go_system_info.systemId").Scan(&results) db.Table("table0"). Select("table0.field0, table0.field1"). Joins("join table1 on table0.field0=table1.field0"). Where("table0.field0=? and table1.field1=?", foo, bar). First(&obj) https://gorm.io/zh_CN/docs/index.html https://cloud.tencent.com/developer/article/1674450

2013-06-20 · 1 min · 34 words · -