??xml version="1.0" encoding="utf-8" standalone="yes"?>
Spark是Openfire的客LQ?br />
Red5是基于java的flash媒体服务器
以后有兴就研究一下子?/p>
public class PiBinaryDigitsCalculator {
/**
* Returns the coefficient of 2^n in the binary
* expansion of pi.
* @param n the binary digit of pi to calculate.
* @throws ValidityCheckFailedException if the validity
* check fails, this means the implementation is buggy
* or n is too large for sufficient precision to be
* retained.
*/
public byte calculateBinaryDigit(final int n) {
return runBBPAlgorithm(n);
}
private byte runBBPAlgorithm(final int n) {
// Lengthy routine goes here ...
}
}
import java.util.HashMap;
public class PiBinaryDigitsCalculator {
private HashMap cache = new HashMap();
public synchronized byte calculateBinaryDigit(
final int n) {
final Integer N = new Integer(n);
Byte B = (Byte) cache.get(N);
if (B == null) {
byte b = runBBPAlgorithm(n);
cache.put(N, new Byte(b));
return b;
} else {
return B.bytevalue();
}
}
private byte runBBPAlgorithm(final int n) {
// Lengthy routine goes here ...
}
}
public interface BinaryDigitsCalculator {
public byte calculateBinaryDigit(final int n);
}
public class PiBinaryDigitsCalculator
implements BinaryDigitsCalculator {
public byte calculateBinaryDigit(final int n) {
return runBBPAlgorithm(n);
}
private byte runBBPAlgorithm(final int n) {
// Lengthy routine goes here ...
}
}
import java.util.HashMap;
public class CachingBinaryDigitsCalculator implements
BinaryDigitsCalculator {
private BinaryDigitsCalculator binaryDigitsCalculator;
private HashMap cache = new HashMap();
public CachingBinaryDigitsCalculator(
BinaryDigitsCalculator calculator) {
this.binaryDigitsCalculator = calculator;
}
public synchronized byte calculateBinaryDigit(int n) {
final Integer N = new Integer(n);
Byte B = (Byte) cache.get(N);
if (B == null) {
byte b =
binaryDigitsCalculator.calculateBinaryDigit(n);
cache.put(N, new Byte(b));
return b;
} else {
return B.bytevalue();
}
}
}
当调用静态方法memoize的时?会创徏一个新的代理实?也就是一个java.lang.reflect.proxy的实?实现了一个接口集.q个接口集由object.getClass().getInterfaces()来决?每个代理实例包含一个java.lang.reflect.InvocationHandler实例来处理这个代理实例调用的相关Ҏ.在我们的例子?Memoizer是一个InvocationHandler实例.
当一个方法在代理实例里被调用,比如, calculateBinaryDigit,那么, Memoizer实例里的invokeҎ׃被调?相关信息会传linvokeҎ,以决定proxy实例调用了哪个方?包含参数信息.在我们的例子?传入Memoizer的java.lang.Method参数是calculateBinaryDigit,而参C息则是pi需要精的位数-整数n.在这个基?Memoizer能够q一步进行缓存操作的.
在例子里(caches是一个Hashmap,cache是一个map)里用到的Key,主要是传入的Ҏ信息:Method对象和参数对? Z实现的简单与通用?Memoizer有一个关于cache的HashMap caches,每个method是一个key,对应的valueZ个cache.然后把参C息{化成一个List对象,作ؓcache的Key.使用List是很方便?同时也可以保证equals()Ҏ,所以能够保证当且仅当参C息完全相同的时候这个List才相{?
一旦一个cache的Key被创?那么,计算之前都会先查找这个cache,如果扑ֈ,则返回cache里的?否则,如果带有q些参数的这个方法没有被调用q?那么,则会通过invoke来调用这个method.在我们的例子? 实例PiBinaryDigitsCalculator 里的calculateBinaryDigitҎ会通过invoke被调?而且计算l果会被存在cache?
何时使用Memoizer
作ؓ一条通用的规?Memoizer能够在Q何需要传l的cache的时候?比如上面提到的例? 特别?接口里每个需要用记忆功能的method需要满下面几条条?
1. q个method的返回值最好不要每ơ调用都会改变\r
2. q个method不要有副效应
3. q个method的参数是定?非mutable?
昄,如果每次调用q个methodq回值都不同,那么cache毫无用处了.同样也是很重要的一Ҏ,因ؓ有副效应的method不会被重?所以这个method不能有副效应(method自动更新某些状?.当然,voidҎ除外.
同样,memorize一个带有未?mutable)参数的method是很危险?因ؓ,要把q些参数储存到hashmap里会是很危险的一件事.ҎMap的定?当这个Map里的key发生改变,Map是不知道?所?当你执行了一ơ这个method之后,相关信息dq了Map,然后参数发生变异(mutate),W二ơ调用的时?׃得到错误的结?
性能
使用cache的主要目的就是ؓ了提升你的程序的速度.然?reflection是众所周知的低?在jdk1.4里有所改进,通过reflection调用Ҏ是普通调用速度?/2,q个比jdk1.3要快40?.Memoizer主要依靠reflection来调用方?所?它看上去q不是一个好的途径.但是,如果使用cache能给E序速度带来的提升远高于reflection寚w度的媄?那么,使用Memoizer是值得考虑?
在我们对PiBinaryDigitsCalculator的测试中,试环境为jdk1.4,当n于10的时?使不使用cache速度是相当的.但是,当n增大的时?使用cache的优势就开始显C出?所?l常使用PiBinaryDigitsCalculator的用?可以考虑使用cache.
不幸的是,唯一试你的E序是否需要cache的途径是比较你的程序在两种情况下的q行效率.管如此,因ؓZ个程序构造一个cache包装器是很容易的一件事,U除它也是很Ҏ?下面的徏议可以作Z个参考的步骤:
1. 选择需要记忆操作的c\r
2. q行它\r
3. 如果效率是满意的,go to 6
4. dmemoizer,使用cache
5. 如果效率没有显著提升,Udmemoizer
6. 如果需?重试.
理论?你需要分析ؓ一个类d记忆功能Ҏ个系l的影响.只有你自己清楚是否值得d.有些Ҏ,即是计量很大?但是在这个系l里很少被调?所?没必要ؓ它添加记忆功?Z保证q个,我开发了一个更有特点的Memoizer,实现了一个叫做CacheStatistics的接?你能从它得到cache的数量以及无效的cache.你可以用它作ؓ判断的一个尺?
扩展Memoizer
修改MemoizercL支持不同的cache{略是很单的.一个比较普通的cd是Least-Recently-Used(LRU)cahce,拥有固定数量的入?q个cache保入口不大于它的最大数?如果过,摒弃最旧的~存数据.也就?能够从cache里得到的是新的数?一个类可以使用LRU cache来防止一个程序长期保持一个状?你可以仅仅传递一个参数给CacheFactory里的memoizeҎ来选择你需要的cachecd.下面的例?LRU cache最多有1000个入?
BinaryDigitsCalculator calculator =
(BinaryDigitsCalculator) Memoizer.memoize(
new PiBinaryDigitsCalculator(),
new LruCacheFactory(1000)
);
即是这么简?Memoizer也应该是javaE序员一个有用的工具.
XMLRPC is message (XML) based and you can not use object at all. The advantage is security and reliability. With XML you can encrypt and validate any way you like. SOAP is XMLRPC on HTTP by XML message
private JButton button;
public MnemonicT() {
super("Mnemonic Test");
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(320, 240));
panel.setLayout(new FlowLayout());
button = new JButton(new AbstractAction("ClickTimes:" + count) {
public void actionPerformed(ActionEvent e) {
button.setText("ClickTimes:" + (++count));
}
});
panel.add(button);
add(panel);
InputMap im = button.getInputMap(JButton.WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke("control A"), "buttonAction"); // 按CTRL+A
button.getActionMap().put("buttonAction", button.getAction());
pack();
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new MnemonicT().setVisible(true);
}
});
}
}