呵呵,感觉转了一个弯:
Benq在以前的帖子中曾建议“使用Spring时,仔细考虑是否到底需要使用Singleton,能不用尽量不用。”
我们现在反过来看看,这句话也不尽合理吧?
是不是应该改为“慎重考虑所提供的bean类在实际应用中,多线程情况下的处理方式”,而不是一句简单的“能不用Singleton就不用Singleton”
呵呵,感觉转了一个弯:
Benq在以前的帖子中曾建议“使用Spring时,仔细考虑是否到底需要使用Singleton,能不用尽量不用。”
我们现在反过来看看,这句话也不尽合理吧?
是不是应该改为“慎重考虑所提供的bean类在实际应用中,多线程情况下的处理方式”,而不是一句简单的“能不用Singleton就不用Singleton”
本想等readonly来贴的,这两天也不知到哪去了,我就帮他贴一下吧,有兴趣的人可以看看吧,
readonly不会反对吧?readonly原来就是。。。嘿嘿,不说了:)
以下是readonly和Doug Lea的email(readonly copy了我),Doug Lea也是真够热心的,每次都很快就答复了。
我发现我也真够笨的,jdk1.5下面就带了源码的,我还去反编译干嘛:(
昨天看了下HashMap的源码,发现Doug Lea也是作者之一呀!
|
|
|
|
Doug Lea只是反复强调HashMap不是Thread safe, 要使用他写的ConcurrentHashMap, 偶尝试着写代码去模拟他说的可能会获得一个完全不同值的情况, 结果却实现不了, 偶的小脑袋是想不明白为什么了......
不使用同步哪里谈到什么同步问题?即使同步也不会形成什么严重的性能问题啊?单态的东西本身就不可能总是提供给你调用synchronized方法。需要做同步的方法调用率是很低的。
好久没看 发现原来大家还在这里:)
还是说几句吧。
有关“破坏结构”这个词,我认为是说对约定的数据结构规则的破坏
在只有一个key的时候size=2 也许你不care,对你没有什么影响 但是确确实实违反了对map的约定。这应该是没有什么辩驳的。
也许在这个应用里无关大局,但是也许在某些地方这就是定时炸弹。
目前除了size问题之外,不知道还没有其他的例子说明并发引起的问题?大家可以都想想。算是互相提高吧.
另外,Lea 是这方面的权威,觉得目前还是应该相信他,起码他的方法万无一失
许多没有正确同步的程序在某些情况下似乎工作得很好,例如在轻微的负载下、在单处理器系统上,或者在具有比 JMM 所要求的更强的内存模型的处理器上。
这篇文章也许有用 http://www-900.ibm.com/developerWorks/cn/java/j-jtp02244/
讨论这么多,还是用最近一期TSS上老外的话说:
"Singleton 是邪恶的",具体文章见:
http://www.pyrasun.com/mike/mt/archives/2004/11/06/15.46.14/index.html
在段落:Using the example with IoC中,第一个就是:Singletons are evil。
注意这篇文章是在最近发表的,可不是在我之前,否则又有人说我“抄袭”了。
多线程代码确实不大容易写。
《程序员》第11期101页《Java多线程编程实例》的最后一个用TreeMap实现cache的例子,按照他书上的代码可能要死锁,而他的源码则犯了和上面所说的对HashMap并发读写同样的错误 -- 对TreeMap在未同步的情况下并发写。
我也从来没有听说过Singleton的性能问题。
我们是用Java做邮件系统的,MTA都是用Java实现的,涉及到众多
多线程的程序,性能方面考虑的也不少。没有觉得Singleton会带来什么性能问题,如果说性能问题也只是说因为不合理的程序而导致的。
与Singleton没有关系。
一般我们性能优化遵循一些基本的准则:
1. 减少内存的开辟,复用提高效率。
2. 减少对象的构造,复用已经创建的对象。
3. 减少消耗时间的操作频率(采用Cache等)
4. 用基于byte[]的操作来代替字符串的操作
....
根据上面的 2 3 原则来分析下面的程序:
这样的程序,如果大部分时间耗费在calcTemperature上,那么这个程序应该用下面的程序来代替:
private Map _tempCache;
public Long getTemperature(String city) {
if(!_tempCache.contains(city)) {
Long result = calcTemperature(city);
_tempCache.put(city, result);
}
return (Long) _tempCache.get(city);
}
//替换程序
private Map _tempCache;
public Long getTemperature(String city)
{
//直接获取
Long result = _tempCache.get(city);
if (result == null) {
//如果不存在 Double Checking
synchronized(this) {
//因为内存操作比起计算或者从数据库获取快很多
result = _tempCache.get(city);
if (result == null) {
result = calcTemperature(city);
_tempCache.put(city, result);
}
}
}
return result;
}
To Readonly:
逻辑上说,没发现不能说明不存在,所以你也没有反驳到Doug Lea.
个人感觉Doug Lea说的没错,你没有产生出错值也许是因为你的电脑只有一个cpu所以你的threads其实并没有真正同时运行过。如果有两个cpu一个在读另一个在写同一个健得话感觉是有可能会出错的。没试过因为没条件。
不知道读和写不同步会不会产生什么问题?我个人在想能不能把实例对象或者是调用hashMap的put方法放到一个同步的过程中,而读取的过程不进行同步,不知道这样会不会有问题呢?下面是我的写法,还没有测试,希望大家指正。
|
老兄也太搞笑了,你是不是以为Doug在做广告啊?要想模拟出来你应该多找几种不同架构的机器试试,在你的机子上估计这辈子都没希望看到你期望的结果了
不好意思头回发帖,
上一个 to ReadOnly
Page 19, line 7 (excluding code)
/*
* Project : JAction
*
* Package : net.xini.jaction.thread
* FileName : BreakHashMap.java
*
* @auther : xini
* 2005-11-8 21:39:23
*
* Copyright : www.xinitek.com
*/
package net.xini.jaction.thread;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class BreakHashMap
{
private static final int THREAD_COUNT = 500;
private static final BooleanLock startLock = new BooleanLock();
private static final IntLock endLock = new IntLock();
public static void main(String[] args)
{
while (true)
{
System.out.print(".");
final Map map = new HashMap();
// init locks
endLock.count = THREAD_COUNT;
startLock.locked = true;
// construct THREAD_COUNT threads
for (int i = 0; i < THREAD_COUNT; i++)
{
new Thread()
{
public void run()
{
//System.out.print("#");
// wait for main thread to kick off
synchronized (startLock)
{
try
{
while (startLock.locked)
{
startLock.wait();
}
}
catch (InterruptedException ie)
{
ie.printStackTrace();
}
}
// put the same key value pair
map.put("key1", "value1");
//如果象下面这样,再put一个,结果就是正确的了,为什么呢?
map.put("key2", "value2");
//map.put("key3", "value3");
synchronized (endLock)
{
endLock.count--;
if (endLock.count == 0)
{
// notify main thread
endLock.notify();
}
}
}
}.start();
}
// kick off
synchronized (startLock)
{
startLock.locked = false;
startLock.notifyAll();
}
// wait for all other thread to end
try
{
synchronized (endLock)
{
while (endLock.count > 0)
{
endLock.wait();
}
}
}
catch (InterruptedException ie)
{
ie.printStackTrace();
}
// check map size
synchronized (map)
{
if (map.size() > 1)
{
System.out.println("\nsize: " + map.size());
Iterator iterator = map.keySet().iterator();
while (iterator.hasNext())
{
String strKey = (String)iterator.next();
System.out.println(map.get(strKey));
}
break;
}
}
// failed, continue
}
}
}
class BooleanLock
{
boolean locked;
}
class IntLock
{
int count;
}
现在有时间并且爱钻牛角尖的人还真多。