-
外形特征
外形有小(郊狼)、中(森林狼)、大(草原狼),吻尖长,眼角微上挑。因为产地和基因不同,所以毛色也不同。常见灰黄两色,还有黑红白等色,个别还有紫蓝等色,胸腹毛色较浅。腿细长强壮,善跑。灰狼的体重和体型大小各地区不一样,一般有随纬度的增加而成正比增加的趋势这一说法. 一般来说,肩高在( 26-36英寸) ,体重32-62公斤( 70-135磅) 野生狼体重记录--------其中1939年在阿拉斯加被打死的一只,,当时80公斤( 175磅) . 最小的狼是阿拉伯狼,雌性的狼有的体重可低至10公斤( 22磅) 狼群适合长途迁行捕猎.其强大的背部和腿部,能有效地舒展奔跑.
生活习性
狼是群居性极高的物种。一群狼的数量大约在5到12只之间,在冬天寒冷的时候最多可到四十只左右,通常以家庭为单位的家庭狼由一对优势对偶领导,而以兄弟姐妹为一群的则以最强一头狼领导。狼群有领域性,且通常也都是其活动范围,群内个体数量若增加,领域范围会缩小。群之间的领域范围不重叠,会以嚎声向其他群宣告范围。幼狼成长后,会留在群内照顾弟妹,也可能继承群内优势地位,有的则会迁移出去(大都为雄狼)而还有一些情况下会出现迁徙狼,以百来头为一群,有来自不同家庭等级的各类狼,各个小团体原狼首领会成为头狼,头狼中最出众的则会成为狼王。野生的狼一般可以活12——16年,人工饲养的狼有的可以活到二十年左右。 奔跑速度极快,可达五十五公里左右,持久性也很好。它们有能力以速度10公里/小时(六英里)长时间奔跑 , 并能以高达近65公里/小时速度( 40英里) 追猎冲刺。 如果是长跑,它的速度会超过猎豹。智能颇高,可以气味、叫声沟通。狼是以肉食为主的杂食性动物,是生物链中极关键的一节。
生长繁殖
狼的怀孕期为61天左右。低海拔的狼一月交配,高海拔则在四月交配。
小狼两周后睁眼,五周后断奶,八周后被带到狼群聚集处。
狼成群生活,雌雄性分为不同等级,占统治地位的雄狼和雌狼随心所欲进行繁殖,处于低下地位的个体则不能自由选择。雌狼产子于地下洞穴中,雌狼经过六十叁天的怀孕期,生下叁只到九只小狼,也有生十几只的。没有自卫能力的小狼,要在洞穴里过一段日子,公狼负责猎取食物。小狼吃奶时期大约有五、六个月之久,但是一个半月也可以吃些碎肉。叁、四个月大的小狼就可以跟随父母一道去猎食。半年后,小狼就学会自己找食物吃了。狼的寿命大约是十二到十四年。在群体中成长的小狼,非但父母呵护备至,而且,族群的其他份子也会爱护有加。狼和非洲土狼会将杀死的猎物,撕咬成碎片,吃下腹内,待回到小狼身边时,再吐出食物反哺。赤狼有时也会在族群中造一育儿所,将小狼集中养育,由母赤狼轮流抚育小狼,毫无怨尤。因此,我们可以说狼的家庭观念极强。
狼的行为模式和身体语言
一般占优势主导地位的狼会身挺高腿直,神态坚定,耳朵是直立向前。
往往尾部纵向卷曲朝背部。这种显示的是级别高主导地位的狼可能一直盯着一个唯唯诺诺的地位低下的狼。
活跃--玩耍时,狼会全身伏低,嘴唇和耳朵向两边拉开,有时会主动舔或快速伸出舌头。
愤怒--愤怒的狼的耳朵会竖立,背毛也会竖立,唇可卷起或后翻,门牙露出,有时也会弓背或咆哮。.
恐惧--害怕时狼会试图把它的身子显得较小,从而不那么显眼,或拱背防守,尾收回。
文化
狼本身并无所谓狡猾或贪婪之本性,但狼在狩猎时的习性以及智慧,往往被引申为凶残恶毒,并用来形容贪婪,凶邪或忘恩负义的人,如“狼心狗肺”,“狼狈为奸”,“狼子野心”等。另外欧亚中部游牧民族因其生存环境,可能会崇拜合群,勇猛的狼,突厥、乌孙都以狼为图腾。 -
2009-10-12
教条示龙场诸生(明.王守仁) - [读书]
诸生相从于此,甚盛。恐无能为助也,以四事相规,聊以答诸生之意。一曰立志,二曰勤学,三曰改过,四曰责善。其慎听,毋忽!
立志
志不立,天下无可成之事。虽百工技艺,未有不本于志者。今学者旷废隳惰,玩岁愒时,而百无所成,皆由于志之未立耳。故立志而圣,则圣矣;立志而贤,则贤矣;志不立,如无舵之舟,无衔之马,漂荡奔逸,终亦何所底乎?昔人所言:“使为善而父母怒之,兄弟怨之,宗族乡党贱恶之,如此而不为善,可也。为善则父母爱之,兄弟悦之,宗族乡党敬信之,何苦而不为善、为君子?使为恶而父母爱之,兄弟悦之,宗族乡党敬信之,如此而为恶,可也。为恶则父母怒之,兄弟怨之,宗族乡党贱恶之,何苦必为恶、为小人?”诸生念此,亦可以知所立志矣。
勤学
已立志为君子,自当从事于学。凡学之不勤,必其志之尚未笃也。从吾游者,不以聪慧警捷为高,而以勤确谦抑为上。诸生试观侪辈之中,苟有“虚而为盈,无而为有”讳己之不能,忌人之有善,自矜自是,大言欺人者,使其人资禀虽甚超迈,侪辈之中,有弗疾恶之者乎?有弗鄙贱之者乎?彼固将以欺人,人果遂为所欺,有弗窃笑之者乎?苟有谦默自持,无能自处,笃志力行,勤学好问;称人之善,而咎己之失;从人之长,而明己之短;忠信乐易,表里一致者;使其人资禀虽甚鲁钝,侪辈之中,有弗称慕之者乎?彼固以无能自处,而不求上人,人果遂以彼为无能,有弗敬尚之者乎?诸生观此,亦可以知所从事于学矣!
改过
夫过者,自大贤所不免;然不害其卒为大贤者,为其能改也。故不贵于无过,而贵于能改过。诸生自思,平日亦有缺于廉耻忠信之行者乎?亦有薄于孝友之道,陷于狡诈、偷刻之习者乎?诸生殆不至于此。不幸或有之,皆其不知而误蹈,素无师友之讲习规饬也。诸生试内省,万一有近于是者,固亦不可以不痛自悔咎;然亦不当以此自歉,遂馁于改过从善之心。但能一旦脱然洗涤旧染,虽昔为盗寇,今日不害为君子矣!若曰吾昔已如此,今虽改过而从善,人将不信我,且无赎于前过,反怀羞涩疑沮,而甘心于污浊终焉,则吾亦绝望尔矣!
责善
“责善,朋友之道;”然须“忠告而善道之”,悉其忠爱,致其婉曲,使彼闻之而可从,绎之而可改,有所感而无所怒,乃为善耳!若先暴白其过恶,痛毁极诋,使无所容,彼将发其愧耻愤恨之心;虽欲降以相从,而势有所不能。是激之而使为恶矣!故凡讦人之短,攻发人之阴私,以沽直者,皆不可以言责善。虽然,我以是而施于人,不可也;人以是而加诸我,凡攻我之失者,皆我师也,安可以不乐受而心感之乎?某于道未有所得,其学卤莽耳。谬为诸生相从于此.每终夜以思,恶且未免,况于过乎?人谓“事师无犯无隐”,而遂谓师无可谏,非也。谏师之道,直不至于犯,而婉不至于隐耳。使吾而是也,因得以明其是;吾而非也,因得以去其非。盖教学相长也。诸生责善,当自吾始。 -
临江之麋
临江之人,畋得麋麑,畜之。入门,群犬垂涎,扬尾皆来。其人怒,怛之。自是日抱就犬,习示之,使勿动,稍使与之戏。积久,犬皆如人意。麋麑稍大,忘己之麋也,以为犬良我友,抵触偃仆,益狎。犬畏主人,与之俯仰甚善。然时啖其舌。
三年,麋出门,见外犬在道甚众,走欲与为戏。外犬见而喜且怒,共杀食之,狼藉道上。麋至死不悟。
黔之驴
黔无驴,有好事者船载以入。至则无可用,放之山下。虎见之,庞然大物也,以为神。蔽林间窥之,稍出近之,慭慭然,莫相知。
他日,驴一鸣,虎大骇,远遁,以为且噬己也,甚恐。然往来视之,觉无异能者,益习其声,又近出前后,终不敢搏。稍近益狎,荡倚冲冒,驴不胜怒,蹄之。虎因喜,计之曰:“技止此耳!”因跳踉大㘎,断其喉,尽其肉,乃去。
噫,形之庞也类有德,声之宏也类有能,向不出其技,虎虽猛,疑畏卒不敢取;今若是焉,悲夫!
永某氏之鼠
永有某氏者,畏日,拘忌异甚。以为己生岁直子,鼠,子神也,因爱鼠,不畜猫犬,禁僮勿击鼠。仓廪庖厨,悉以恣鼠不问。
由是鼠相告,皆来某氏,饱食而无祸。某氏室无完器,椸无完衣,饮食大率鼠之余也。昼累累与人兼行,夜则窃啮斗暴,其声万状,不可以寝,终不厌。
数岁,某氏徙居他州。后人来居,鼠为态如故。其人曰:“是阴类恶物也,盗暴尤甚,且何以至是乎哉?”假五六猫,阖门,撤瓦灌穴,购僮罗捕之。杀鼠如丘,弃之隐处,臭(上自下死)数月乃已。
呜呼!彼以其饱食无祸为可恒也哉! -
JNI即是Java Native Interface,主要用来Java和其他语言之间的交互,多半是和平台依赖的调用、其他高级语言的库甚至是低级语言交互。相信大家平时在JDK中看到很多native的方法,但是自己写JNI应用的会确很少。这次因为在进行开发中,遇到需要Java调用一个现成的成熟的功能完善的C语言应用库,因此 JNI便成了Java和C库之间的桥的功能。既然是初探,那么下面我们就从HelloWorld开始吧:虽然Java是一个跨平台的语言,但是C语言是一个和平台密切相关的语言;所以针对Unix、Linux、Windows等不同的操作系统,C语言的预编译,动态库的创建等都有一些差别,也需要我们分别进行处理之。下面仅基于Sun的Unix平台Sun Solaris开发为例。
1.首先声明第一个Java native程序:HelloWorld.java。
public class HelloWorld {
static {
init();
}
private native int hello();
public int sayHello() {
return hello();
}
/**
* @param args
*/
public static void main(String[] args) {
HelloWorld hw = new HelloWorld();
System.out.println("Say in Java:" + hw.sayHello());
}
private static void init() {
System.out.println("Starting to load HelloWorld lib.");
try {
System.loadLibrary("HelloWorld");
} catch (Throwable t) {
System.out.println("Load unsuccessfully.");
t.printStackTrace();
System.exit(-1);
}
System.out.println("Load successfully.");
}
}
2.编译该Java文件。
javac HelloWorld.java
3.生成相应的C语言的HelloWorld.h头文件,javah HelloWorld,头文件内容如下:(其中,static Java方法和非static Java方法经过javah -jni生成的C头文件是有区别的,差异在于参数,static Java方法生成的相应的C方法的第二个参数是jclass类型,非static Java方法生成的相应的C方法的第二个参数是jobject类型。)
more HelloWorld.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */
#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloWorld
* Method: hello
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_HelloWorld_hello
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
4.开始编写第一个c语言的JNI的本地(native)方法:
vi HelloWorld.c
#include <jni.h>
#include "HelloWorld.h"
#include <stdio.h>
JNIEXPORT jint JNICALL Java_HelloWorld_hello
(JNIEnv* env, jobject target)
{
printf("Hello World in C program!!!\n");
return 2;
}
5.生成Unix下的动态库.so文件:
cc -G -I. -I$JAVA_HOME/include -I$JAVA_HOME/include/solaris HelloWorld.c -o libHelloWorld.so
在当前目录下看到新生成的libHelloWorld.so文件。也许你会注意到我们在Java程序中System.loadLibrary()加载的是库HelloWorld,那么这其实是一个命名的规范而已。以lib开头的.so文件即是Unix下的动态库,而JNI加载器通过HelloWorld这个名字实际上希望加载的动态库是libHelloWorld.so。
6.设置环境变量,查看LD_LIBRARY_PATH并设置:
vi .cshrc
setenv LD_LIBRARY_PATH '.:/usr/local/lib:$LD_LIBRARY_PATH'
source .cshrc
这个环境变量设置的是Java的动态库加载器需要加载的C动态库所在的路径。因此,我们生成的libHelloWorld.so一定要在这个环境变量中设置,在这个例子中我就把当前目录.加到环境变量LD_LIBRARY_PATH了:)
7.执行HelloWorld文件,java HelloWorld,在标准输出上看到:
Starting to load HelloWorld lib.
Load successfully.
Hello World in C program!!!
Say in Java:2
一切Okey,如此的easy,一阵狂喜!接下来就是将这个例子运用于JNI的开发之中了。
Resource:
《Java Native Interface: Programmer's Guide and Specification》
http://java.sun.com/docs/books/jni/html/start.html#27008
http://linuxmafia.com/faq/Admin/ld-lib-path.html
https://www6.software.ibm.com/developerworks/cn/education/java/j-jni/tutorial/j-jni-2-15.html -
2008-03-31
Java NIO TCP编程 - [Java]
在Java1.4以前,Java的网络编程是只有阻塞方式的,在Java1.4以及之后,Java提供了非阻塞的网络编程API.从Java的发展来看,由于Java的快速发展,JVM性能的提升,涉足到服务端应用程序开发也越来越多,要求高性能的网络应用越来越多,这是Java推出非阻塞网络编程的最主要原因吧。
对我而言,以前的大部分服务端应用主要是搭建在应用服务器之上,所以通讯这部分工作都是有应用服务器来实现和管理的。这次由于通讯和协议,我们必须自己实现一个能处理大量并发客户端的高性能并行处理的Java服务端程序。因此,选择非阻塞的处理方式也是必然的。我们首先来看看阻塞的处理方式:
在阻塞的网络编程方式中,针对于每一个单独的网络连接,都必须有一个线程对应的绑定该网络连接,进行网络字节流的处理。下面是一段代码:
public static void main(String[] args) {
try {
ServerSocket ssc = new ServerSocket(23456);
while (true) {
System.out.println("Enter Accept:");
Socket s = ssc.accept();
try {
(new Thread(new Worker(s))).start();
} catch (Exception e) {
// TODO
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static class Worker implements Runnable {
private Socket s;
private boolean running = true;;
public Worker(Socket s) {
this.s = s;
}
public void run() {
try {
InputStream is = s.getInputStream();
OutputStream os = s.getOutputStream();
while (running) {
byte[] b = this.readByLength(is, 1024);
this.process(b);
}
} catch (Throwable t) {
// TODO
t.printStackTrace();
}
}
private byte[] readByLength(InputStream is, int contLen) throws IOException {
byte[] b = new byte[contLen];
int off = 0;
int length = 0;
while ((length = is.read(b, off, contLen - off)) >= 0) {
off = +length;
if (off >= contLen) {
break;
}
}
return b;
}
private void process(byte[] b) {
}
}
在这段代码中,我们看到有两个阻塞的方法,是ServerSocket的accept()方法;和InputStream的read()方式。因此我们需要两类型的线程分别进行处理。而且每一个阻塞方法所绑定的线程的生命周期和网络连接的生命周期是一致的。基于以上的原因,NIO应运而生,一方面,为每一个网络连接建立一个线程对应,同时每一个线程有大量的线程处于读写以外的空闲状态,因此希望降低线程的数量,降低每个空闲状态,提高单个线程的运行执行效率,实际上是在更加充分运用CPU的计算、运行能力(因为,如果有大量的链路存在,就存在大量的线程,而大量的线程都阻塞在read()或者write()方法,同时CPU又需要来回频繁的在这些线程中间调度和切换,必然带来大量的系统调用和资源竞争.);另外一方面希望提高网络IO和硬盘IO操作的性能。在NIO主要出现了三个新特性:
1.数据缓冲处理(ByteBuffer):由于操作系统和应用程序数据通信的原始类型是byte,也是IO数据操作的基本单元,在NIO中,每一个基本的原生类型(boolean除外)都有Buffer的实现:CharBuffer、IntBuffer、DoubleBuffer、ShortBuffer、LongBuffer、FloatBuffer和ByteBuffer,数据缓冲使得在IO操作中能够连续的处理数据流。当前有两种ByteBuffer,一种是Direct ByteBuffer,另外一种是NonDirect ByteBuffer;ByteBuffer是普通的Java对象,遵循Java堆中对象存在的规则;而Direct ByteBuffer是native代码,它内存的分配不在Java的堆栈中,不受Java内存回收的影响,每一个Direct ByteBuffer都是直接分配的一块连续的内存空间,也是NIO提高性能的重要办法之一。另外数据缓冲有一个很重要的特点是,基于一个数据缓冲可以建立一个或者多个逻辑的视图缓冲(View Buffer).比方说,通过View Buffer,可以将一个Byte类型的Buffer换作Int类型的缓冲;或者一个大的缓冲转作很多小的Buffer。之所以称为View Buffer是因为这个转换仅仅是逻辑上,在物理上并没有创建新的Buffer。这为我们操作Buffer带来诸多方便。
2.异步通道(Channel):Channel是一个与操作系统紧密结合的本地代码较多的对象。通过Channel来实现网络编程的非阻塞操作,同时也是其与ByteBuffer、Socket有效结合充分利用非阻塞、ByteBuffer的特性的。在后面我们会看到具体的SocketChannel的用法。
3.有条件的选择(Readiness Selection):大多数操作系统都有支持有条件选择准备就绪IO通道的API,即能够保证一个线程同时有效管理多个IO通道。在NIO中,由Selector(维护注册进来的Channel和这些Channel的状态)、SelectableChannel(能被Selector管理的Channel)和SelectionKey(SelectionKey标识Selector和SelectableChannel之间的映射关系,一旦一个Channel注册到Selector中,就会返回一个SelectionKey对象。SelectionKey保存了两类状态:对应的Channel注册了哪些操作;对应的Channel的那些操作已经准备好了,可以进行相应的数据操作了)结合来实现这个功能的。
NIO非阻塞的典型编程模型如下:
private Selector selector = null;
private static final int BUF_LENGTH = 1024;
public void start() throws IOException {
if (selector != null) {
selector = Selector.open();
}
ServerSocketChannel ssc = ServerSocketChannel.open();
ServerSocket serverSocket = ssc.socket();
serverSocket.bind(new InetSocketAddress(80));
ssc.configureBlocking(false);
ssc.register(selector, SelectionKey.OP_ACCEPT);
try {
while (true) {
int nKeys = UnblockServer.this.selector.select();
if (nKeys > 0) {
Iterator it = selector.selectedKeys().iterator();
while (it.hasNext()) {
SelectionKey key = (SelectionKey) it.next();
if (key.isAcceptable()) {
ServerSocketChannel server = (ServerSocketChannel) key.channel();
SocketChannel channel = server.accept();
if (channel == null) {
continue;
}
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_READ);
}
if (key.isReadable()) {
readDataFromSocket(key);
}
it.remove();
}
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
/**
* @param key
* @throws IOException
*/
private void readDataFromSocket(SelectionKey key) throws IOException {
ByteBuffer buf = ByteBuffer.allocate(BUF_LENGTH);
SocketChannel sc = (SocketChannel) key.channel();
int readBytes = 0;
int ret;
try {
while ((ret = sc.read(buf.buf())) > 0) {
readBytes += ret;
}
} finally {
buf.flip();
}
// process buffer
// buf.clear();
}
从这段程序,我们基本可以了解到NIO网络编程的一些特点,创建一个SocketServer的方式已经发生了变化,需要指定非阻塞模式,需要创建一个Channel然后注册到Selector中去,同样,建立一个网络连接过程也是一样的模式,然后就是有条件的选择(Readiness Selection).这样,我们的每一个线程只需要处理一类型的网络选择。在代码上,我们发现处理的方式和阻塞完全不一样了,我们需要完全重新考虑如何编写网络通信的模块了:
1.持久连接的超时问题(Timeout),因为API没有直接的支持timeout的参数设置功能,因此需要我们自己实现一个这样功能。
2.如何使用Selector,由于每一个Selector的处理能力是有限的,因此在大量链接和消息处理过程中,需要考虑如何使用多个Selector.
3.在非阻塞情况下,read和write都不在是阻塞的,因此需要考虑如何完整的读取到确定的消息;如何在确保在网络环境不是很好的情况下,一定将数据写进IO中。
4.如何应用ByteBuffer,本身大量创建ByteBuffer就是很耗资源的;如何有效的使用ByteBuffer?同时ByteBuffer的操作需要仔细考虑,因为有position()、mark()、limit()、capacity等方法。
5.由于每一个线程在处理网络连接的时候,面对的都是一系列的网络连接,需要考虑如何更好的使用、调度多线程。在对消息的处理上,也需要保证一定的顺序,比方说,登录消息最先到达,只有登录消息处理之后,才有可能去处理同一个链路上的其他类型的消息。
6.在网络编程中可能出现的内存泄漏问题。
在NIO的接入处理框架上,大约有两种并发线程:
1.Selector线程,每一个Selector单独占用一个线程,由于每一个Selector的处理能力是有限的,因此需要多个Selector并行工作。
2.对于每一条处于Ready状态的链路,需要线程对于相应的消息进行处理;对于这一类型的消息,需要并发线程共同工作进行处理。在这个过程中,不断可能需要消息的完整性;还要涉及到,每个链路上的消息可能有时序,因此在处理上,也可能要求相应的时序性。
当前社区的开源NIO框架实现有MINA、Grizzly、NIO framework、QuickServer、xSocket等,其中MINA和Grizzly最为活跃,而且代码的质量也很高。他们俩在实现的方法上也完全大不一样。(大部分Java的开源服务器都已经用NIO重写了网络部分。 )
不管是我们自己实现NIO的网络编程框架,还是基于MINA、Grizzly等这样的开源框架进行开发,都需要理解确定的了解NIO带来的益处和NIO编程需要解决的众多类型的问题。充足、有效的单元测试,是我们写好NIO代码的好助手:)
Resource:
http://www.cis.temple.edu/~ingargio/cis307/readings/unix4.html#states
《Java NIO》
《GlassFish--开源的Java EE应用服务器》









