我有这样的代码,
public int handle_refresh(Data mmsg) throws Exception {
String custId = mmsg.getCustomerId();
CustomerThread t = custMap.get(mmsg.getCustomerId());
if (t == null || !t.isAlive()) {
t = (CustomerThread) context.getBean("custT");
t.initThread(mmsg.getCustomerId(), mmsg.getCustomerId(), mmsg.getMessageBody());
custSMap.put(mmsg.getCustomerId(), t);
t.createBufferThread();
t.start();
t.initStreaming();
}
synchronized (t) {
if (null != t) {
ret = t.addSymbols(mmsg);
}
}
return ret;
}
}
此处在custMap中检查CustomerThread,
映射custMap = new CustomerThread();
如果在custMap中有线程
1)然后阅读spring appilcation context并获取它。 t = (CustomerThread) context.getBean("custT");
2)在initThread方法中,为每个客户设置唯一的线程名称。 t.initThread(mmsg.getCustomerId(), mmsg.getCustomerId(), mmsg.getMessageBody());
3)然后将新创建的线程放入映射custMap. custSMap.put(mmsg.getCustomerId(), t);
4)然后在createBufferThread中将数据设置为缓存.. t.createBufferThread();
5)然后重新启动线程,然后从db获取数据。 t.start();
6)设置数据库连接
如果在custMap中没有线程
1)synchronized (t) .
2)调用t.addSymbols()
方法。
我的问题是......
1)这里第一个if块只是第一次执行,如果创建了一个线程,那么总是执行synchronized(t)吗?
我的意思是如果块只执行一次,那么以上所有1到6步呢?
2)那么synchronized(t)会做什么?
答案 0 :(得分:1)
我认为sychronized (t)
正在保护addSymbols
方法以使其成为线程安全的。调用此方法是我假设在t
线程内的某些数据结构中添加符号。可能是该线程中的其他方法是synchronized
,这意味着它将锁定在Thread
实例上。这就是sychronized (t)
在这里做的事情。
但这是一种非常难看的添加线程安全的方法。 addSymbols(...)
方法本身应锁定锁定对象,或者,如果需要,可以是synchronized
方法。一个类应该负责它自己的锁定,不要求调用者做某事。
关于您的代码的其他评论:
t = (CustomerThread) context.getBean("custT");
上面的代码似乎是从Spring获取一个线程实例。除非“custT”bean是某种线程工厂,否则这通常是单例。如果它不是工厂bean,那么对于每次调用handle_refresh
方法并重新初始化它,您将获得相同的线程对象。这很可能不是你想要的。
synchronized (t) {
if (null != t) {
ret = t.addSymbols(mmsg);
}
}
如果t
为null
,则synchronized
行会抛出NPE。您不需要null
内的synchronized
检查。
CustomerThread t = custMap.get(mmsg.getCustomerId());
如果从多个线程调用handle_refresh(...)
方法,那么您需要确保custMap
也正确同步。
答案 1 :(得分:0)
if块应该只对每个客户ID执行一次。请注意if块中的这行代码:
custSMap.put(mmsg.getCustomerId(), t);
它会填充地图,因此下次使用该customerId进行搜索时,将会找到它并执行同步块。
Synchronized块将在互斥锁内调用t上的方法。