java简单任务池

转自:http://blog.csdn.net/rcfalcon/article/details/5736972

什么叫任务池?

实际上就是一个任务流水线,可以将各种待完成的任务发布到流水线中。由任务池统计管理并且调度,来保证任务的完成。可能会有这样的疑问:我对每个任务都单独起一个线程,让其独立完成不就可以了么?对于小批量、快速、占用少量资源的任务可能这样没有问题,但是对于大规模、多并发的任务,这样的结果是会造成系统性能极其低下,并且还很可能造成资源需求上的溢出。

如何用有限的资源,调度并完成任务,这就是我们任务池的最终目标。

很直观,直接上任务池中就是有一个队列存储任务对象,对于每个任务它能知道当前任务状态(尚未开始、进行中、已完成)。当一个任务完成的时候,它将该任务清除,并且取出一个其他尚未完成的任务并开启之。

任务池应该具有并发性能,可以限制同时最多有多少个任务并行执行。

好,需求明确了,下面直接看代码吧。该代码实现子任务调用FFMPEG进行视频转码,而任务管理池用于限制并调度任务并发的执行。

转码任务基类

调用示例:

java调用FFmpeg

转自:http://www.ll19.com/archives/92

java调用FFmpeg及mencoder转换视频为FLV并截图,需要FFmpeg及mencoder支持请自行下载,以下为相关程序:

Conver.java

ConverVideo.java

ProcessFlvImg.java

HttpClient超时机制

转自:http://agapple.iteye.com/blog/916837

HttpClient版本是3.0.1

一般的HttpClient使用例子:

这里我给出的一个url是近20MB的一个下载资源,很快发现线程要等个很久。 咋办,得加个timeout超时机制。
Stack线程栈代码

分析

目前httpClient3.1只支持3种timeout的设置:

  • connectionTimeout  :  socket建立链接的超时时间,Httpclient包中通过一个异步线程去创建socket链接,对应的超时控制。
  • timeoutInMilliseconds :  socket read数据的超时时间, socket.setSoTimeout(timeout);
  • httpConnectionTimeout :  如果那个的是MultiThreadedHttpConnectionManager,对应的是从连接池获取链接的超时时间。

分析一下问题,我们需要的是一个HttpClient整个链接读取的一个超时时间,包括请求发起,Http Head解析,response流读取的一系列时间的总和。

目标很明确,对应的修正后的测试代码:

这里通过Thread.join方法,设置了超时时间为5000 ms,这是比较早的用法。 如果熟悉cocurrent包的,可以直接使用Future和ThreadPoolExecutor进行异步处理,缓存对应的Thread。

Cocurrent代码例子代码:

说明: 这里为什么释放链接未采用get.releaseConnection()
看下release的实现:

  • 这里会先关闭responseStream流,这就是问题点。
  • 对应的responseStream是在方法:readResponseBody(HttpConnection conn)。一般的html页面返回的是一个ContentLengthInputStream对象
  • ContentLengthInputStream在调用close方法时会用ChunkedInputStream.exhaustInputStream读完所有流数据
  • ChunkedInputStream.exhaustInputStream代码

说明:

  • 因为非sleep和park的方法,不会响应InterruptedException事件,所以普通future超时发起的Thread.interrpt()并没有效果。
  • 默认的SimpleHttpConnectionManager不支持这样的操作,所以选择MultiThreadedHttpConnectionManager.shutdown()方法,强制关闭底层HttpConnection的sock的输入输出流。

总结

  1. 理解一下HttpClient这样设计的理由: socket重用,keepAlive协议的支持等,保证上一次数据不会对新的请求有影响。
  2. Thread.interrpt()处理,只会在Thread处于sleep或者wait状态才会被唤醒(api的描述)。而且该方法的调用并不自动产生InterruptedException异常,一般是需要自己判断Thread.isInterrupted(),然后throw异常。 我们目前使用的一些jdk cocurrent类比如future.cancel也是类似处理。

tuckey urlrewritefilter的配置

最近在写个小东西,用到了urlrewrite,使用的是tuckey 的urlrewirefilter

下面就说说urlrewritefilter的配置,首先在web.xml中配置filter,定义要过滤的url,注意filter的位置。(官网上面也有的,可以点上面的链接看。)

urlrewritefilter默认会加载urlwrite.xml,所以在WEB-INF目录下创建urlrewrite.xml,使用下面的配置

就可以了。具体的语法可以参考https://urlrewritefilter.googlecode.com/svn/trunk/src/doc/manual/3.0/index.html

最开始配置使用的是4.0版本的dtd,即

发现访问静态资源全部找不到,后台打印的url全部被加了前缀 mpabo, 比如访问的链接是 /css/css.css 会变成 /mpabo/css/css.css

应该是

这规则生效导致的。后来尝试使用3.0的版本,竟然没问题。然后对比了下3.0的dtd和4.0的dtd,发现有个属性不一致,就是to的last, 3.0 默认是 true,4.0 默认为false, 又看了4.0文档的语法

last (optional)  :   false (default) The rest of the “rules” will be processed if this one succeeds.   (true No more “rules” will be processed if this one is a match.)

由于

这规则在最后面,所以即使前面的规则匹配了,但还是被覆盖了。所以解决方法就是改为3.0的dtd,或者在增加last=”true”。看个人喜好了。

再重新去看了下3.0的文档发现last写的竟然也是 false(default),但dtd的定义里面是true,坑人啊。

附3.0的dtd, to的定义:

使用snmp4j实现Snmp功能(三)

转自:http://blog.csdn.net/clearwater21cn/article/details/3125138

前两篇文章讲了如何使用Snmp4j实现Set、Get(使用snmp4j实现Snmp功能(一))以及发送、接收Trap(使用snmp4j实现Snmp功能(二)) 功能。

在我们前面的实现中,如果访问MIB库中不存在的OID,Get方式的话,我们会得到一个Null值,而Set方式时Agent端会把我们发过去的PDU原封不动的返回回来。当然多数情况下这不是我们想要的结果,所以今天我们讲一下如何设置Agent端的Response。

这个功能其实和接收发送Trap是一样的,只不过对象变了一下而已。同样,接收Set和Get的方法写在CommandResponderprocessPdu()中。我们把前面写过的initComm() 的processPdu()中添加一段代码(Agent端):

接下来让Agent端的main()函数调用listen(),运行main()函数,Agent端开始监听来自Manager的Set和Get。

回到本机,向Agent端发送一个Set的PDU或Get的PDU,如果控制台打出我们刚刚在程序中设置的值”MYSNMP”,说明我们的Response设置成功啦!

当然,程序中的设置PDU的Value是一个最简单的Response示例,在实际的应用中,应该要根据不同的OID返回不同的Value,这一部分的代码要根据实际的应用去发挥啦。

使用snmp4j实现Snmp功能(二)

转自:http://blog.csdn.net/clearwater21cn/article/details/2411742

前一篇文章讲了如何用snmp4j实现set和get的功能,今天讲如何接收trap。

snmp4j提供了一个抽象类CommandResponder类用于接收trap,这个类里面有一个必须实现的方法processPdu(),当接收到trap,会自动进入这个方法,因此我们可以将对trap的处理写在这里。

下面修改上篇文章例子中的initComm()方法:

其中targetAddress指Agent端也就是trap发送,transport指trap接收方,这里就是本机,假设IP是192.168.1.2,但注意不能写成127.0.0.1。

因为我们无法得知trap什么时候会发送,所以需要有一个线程等待trap的到来,在这个例子中我们使用wait()来等待trap的到来,具体应用中就要根据实际情况来做了。

将上面的代码添加到原来的例子中,就可以接收trap了。

但是还有一个问题,如何让192.168.1.1发送trap呢?这个也可以使用snmp4j来做。其实发送trap和发送set、get PDU是类似的,同样是发送PDU,只不过类型不一样。我们把前面的例子复制到192.168.1.1,在里面添加一段代码:

这里PDU的OID和Value可以自己构造,无需使用特定的值。

然后修改地址

另外需要修改target的version,即改为target.setVersion(SnmpConstants.version2c)为什么要这样改我也没搞清楚,总之verion1收不到。

接下来修改main()函数,调用setTrap()。

然后回到本机运行刚才的例子,当控制台显示“Waiting for traps..”时,运行Agent端的例子。此时如果192.168.1.2打出我们刚刚设置的PDU的信息,就说明Trap的收发成功了。

使用snmp4j实现Snmp功能(一)

转自:http://blog.csdn.net/clearwater21cn/article/details/2328047

上一篇文章讲了Snmp的一些基本概念(Snmp学习笔记),接下来,我们使用Java的开源组件snmp4j来实现一下Snmp里的各种功能。首先是上一篇文章中的那个例子。即通过snmp获取机器名。

snmp4j的jar包可以在它的官方网站http://www.snmp4j.org/上下载,我就不啰嗦了。

接下来直接贴代码:

上面的这段代码直接参考snmp4j API说明文档中提供的例子,是一个最简单的snmp4j的应用。只要你的机器里安装了snmp通讯组件,上面的代码应该可以运行成功。

在上一个例子中,我们只做了读取的工作,接下来,我们进行一下设置操作,通过Snmp修改读取的机器名。
public的默认权限是只读,要想进行写操作,我们必须进行手动的设置。具体的做法是:进入管理工具→服务,找到Snmp Service→属性→安全。在这个选项卡中我们可以看到public的权限是只读,你可以修改public的权限,也可以重新创建一个community。从安全角度来讲当然应该新建一个,在这里为了测试方便,我就直接给public添加写入权限了。
接下来就可以编写代码了,我把上面的例子重构一下,代码如下:

如果控制台打出“1.3.6.1.2.1.1.5.0 : SNMPTEST”的消息,就说明我们的操作成功啦!

以上代码在WindowsXP下测试成功。

Java解析XML汇总(DOM/SAX/JDOM/DOM4j/XPath)

转自:http://blog.csdn.net/smcwwh/article/details/7183869

目前在Java中用于解析XML的技术很多,主流的有DOM、SAX、JDOM、DOM4j,下文主要介绍这4种解析XML文档技术的使用、优缺点及性能测试。
一、【基础知识——扫盲】
sax、dom是两种对xml文档进行解析的方法(没有具体实现,只是接口),所以只有它们是无法解析xml文档的;jaxp只是api,它进一步封装了sax、dom两种接口,并且提供了DomcumentBuilderFactory/DomcumentBuilder和SAXParserFactory/SAXParser(默认使用xerces解释器)。
二、【DOM、SAX、JDOM、DOM4j简单使用介绍】
1、【DOM(Document Object Model) 】
由W3C提供的接口,它将整个XML文档读入内存,构建一个DOM树来对各个节点(Node)进行操作。
示例代码:

后文代码中有使用到text.xml(该文档放在src路径下,既编译后在classes路径下),都是指该xml文档。

该代码只要稍做修改,即可变得更加简洁,无需一直写if来判断是否有子节点。

2、【SAX (Simple API for XML) 】
SAX不用将整个文档加载到内存,基于事件驱动的API(Observer模式),用户只需要注册自己感兴趣的事件即可。SAX提供EntityResolver, DTDHandler, ContentHandler, ErrorHandler接口,分别用于监听解析实体事件、DTD处理事件、正文处理事件和处理出错事件,与AWT类似,SAX还提供了一个对这4个接口默认的类DefaultHandler(这里的默认实现,其实就是一个空方法),一般只要继承DefaultHandler,重写自己感兴趣的事件即可。
示例代码:

3、【JDOM】
JDOM与DOM非常类似,它是处理XML的纯JAVA API,API大量使用了Collections类,且JDOM仅使用具体类而不使用接口。 JDOM 它自身不包含解析器。它通常使用 SAX2 解析器来解析和验证输入 XML 文档(尽管它还可以将以前构造的 DOM 表示作为输入)。它包含一些转换器以将 JDOM 表示输出成 SAX2 事件流、DOM 模型或 XML 文本文档
示例代码:

4、【DOM4j】
dom4j是目前在xml解析方面是最优秀的(Hibernate、Sun的JAXM也都使用dom4j来解析XML),它合并了许多超出基本 XML 文档表示的功能,包括集成的 XPath 支持、XML Schema 支持以及用于大文档或流化文档的基于事件的处理
示例代码:

三、【性能测试】
环境:AMD4400+ 2.0+GHz主频 JDK6.0
运行参数:-Xms400m -Xmx400m
xml文件大小:10.7M
结果:
DOM: >581297ms
SAX: 8829ms
JDOM: 581297ms
DOM4j: 5309ms
时间包括IO的,只是进行了简单的测试,仅供参考!!!!

四、【对比】
1、【DOM】
DOM是基于树的结构,通常需要加载整文档和构造DOM树,然后才能开始工作。
优点:
a、由于整棵树在内存中,因此可以对xml文档随机访问
b、可以对xml文档进行修改操作
c、较sax,dom使用也更简单。
缺点:
a、整个文档必须一次性解析完
a、由于整个文档都需要载入内存,对于大文档成本高
2、【SAX】
SAX类似流媒体,它基于事件驱动的,因此无需将整个文档载入内存,使用者只需要监听自己感兴趣的事件即可。
优点:
a、无需将整个xml文档载入内存,因此消耗内存少
b、可以注册多个ContentHandler
缺点:
a、不能随机的访问xml中的节点
b、不能修改文档
3、【JDOM】
JDOM是纯Java的处理XML的API,其API中大量使用Collections类,
优点:
a、DOM方式的优点
b、具有SAX的Java规则
缺点
a、DOM方式的缺点
4、【DOM4J】
这4中xml解析方式中,最优秀的一个,集易用和性能于一身。

五、【小插曲XPath】
XPath 是一门在 XML 文档中查找信息的语言, 可用来在 XML 文档中对元素和属性进行遍历。XPath 是 W3C XSLT 标准的主要元素,并且 XQuery 和 XPointer 同时被构建于 XPath 表达之上。因此,对 XPath 的理解是很多高级 XML 应用的基础。
XPath非常类似对数据库操作的SQL语言,或者说JQuery,它可以方便开发者抓起文档中需要的东西。(dom4j也支持xpath)
示例代码:

六、【补充】

注意4种解析方法对TextNode(文本节点)的处理:

1、在使用DOM时,调用node.getChildNodes()获取该节点的子节点,文本节点也会被当作一个Node来返回,如:

输出的结果是:

其中\n的ASCII码为10,\t的ASCII码为9。结果让人大吃一惊,university的子节点数不是1,也不是2,而是3,这3个子节点都是谁呢?为了看得更清楚点,把xml文档改为:

还是上面的程序,输出结果为:

其中数字1的ASCII码为49,数字2的ASCII码为50。
2、使用SAX来解析同DOM,当你重写它的public void characters(char[] ch, int start, int length)方法时,你就能看到。

3、JDOM,调用node.getChildren()只返回子节点,不包括TextNode节点(不管该节点是否有Text信息)。如果要获取该节点的Text信息,可以调用node.getText()方法,该方法返回节点的Text信息,也包括\n\t等特殊字符。

4、DOM4j同JDOM
参考:
http://www.docin.com/p-78963650.html
http://wenku.baidu.com/view/b091f9360b4c2e3f5727638b.html
http://kree.iteye.com/blog/668280

URLClassLoader 读取任意目录下的class

转自:http://blog.csdn.net/lrenjundk/article/details/8105908

今天试验了半天,需要注意的是loadClass函数只能读取.class文件,如果是.java文件会报告ClassNotFound异常,需要先对其进行编译。
另外URLClassLoader 读取的任意目录也包括.jar

java 反射加载指定目录上的Class文件

[转]

最近由于公司android 客服端的兄弟想做动态扩展android应用,而不通过重新发布版本来来实现,所以就考虑到用java的反射加载指定的类

一般加载类的Class.froName的方法,这个方法是加载已经集成或者导入到项目下的jar下面的类
如是找到Class类,发现只有Class.forName的方法
如是去找ClassLoader 发现一个defineClass的方法可以接受字节数组,来生产Class对象,但是在编码工具中Eclipse去实例这个类,在调用这个方法是,竟然发现竟然说这个方法不存在,开始我以为是文档的问题,

后面一想 ,java 中有许多方法是提供给jvm虚拟机用的,编码工具对其进行的过滤,后面同事收到一篇同样需求的代码,一看才想明白,既然不能在外部调用,如果继承这个类,再重写这个方法,就可以实现这样的需求,额,有时候看样子还是想的不够

好了,看实现类代码

再看调用方式

好了再看 Test 类中有哪些方法