Java多线程同步线程

时间:2012-09-10 12:24:23

标签: java multithreading

我有这样的代码,

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)会做什么?

2 个答案:

答案 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);
    }
}

如果tnull,则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上的方法。