Java:多线程复杂的Getter

时间:2015-12-07 09:33:30

标签: java multithreading

我有一个get-method返回非基本类型,应该是线程安全的。

功能描述

我有一个操作在一个单独的线程上。此操作需要IP地址并使用我自己的getter方法从其他类获取它(因为我必须进行一些IP地址计算)。 getter返回InetAddress

代码示例

// This is called in a separate thread.
// How can I make Utility.getMyIp() thread-safe?
InetAddress myIp = Utility.getMyIp();

问题

关于IP-Address getter方法,我需要注意什么?我需要从其他线程使用该方法。我必须让它同步吗?

如果您需要更多信息,请询问!

PS:还有其他线程提出类似的问题,但我发现的那些只讨论原始数据类型,应该足以使用易失性关键字。在这里,我需要返回一个类型InetAddress

编辑:添加代码

这是正在进行的工作(它可能不适用于所有情况,也不是完成代码)。

/**
 * Gets the BroadcastAddress for IPv4.
 * @return
 * @throws SocketException
 */
public static InetAddress getBroadcastAddress4() {

    // Todo: Check other possibility
    System.setProperty("java.net.preferIPv4Stack" , "true");

    // Init
    InetAddress broadcastAddress = null;

    try {
        Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();

        while(interfaces != null && interfaces.hasMoreElements()){
            NetworkInterface currentInterface = interfaces.nextElement();

            if(!currentInterface.isLoopback()){
                for(InterfaceAddress address : currentInterface.getInterfaceAddresses()){
                    InetAddress broadcast = address.getBroadcast();
                    if(broadcast != null){
                        broadcastAddress = broadcast;
                        break;
                    }
                }
            }
        }
    } catch (SocketException e) {
        e.printStackTrace();
    }

    return broadcastAddress;
}

3 个答案:

答案 0 :(得分:1)

代码是线程安全的,无需任何进一步修改。

您还可以将此方法的结果存储到变量中并执行一次实际计算 - 因为在程序运行期间结果不太可能发生变化。懒惰地初始化变量或使用static {}代码块在classload上初始化它。代码可能如下所示:

InetAddress broadcastAddress;

public static InetAddress getBroadcastAddress4() {
    return broadcastAddress;
}

static {
    System.setProperty("java.net.preferIPv4Stack" , "true");

    try {
        Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();

        while(interfaces != null && interfaces.hasMoreElements()){
            NetworkInterface currentInterface = interfaces.nextElement();

            if(!currentInterface.isLoopback()){
                for(InterfaceAddress address : currentInterface.getInterfaceAddresses()){
                    InetAddress broadcast = address.getBroadcast();
                    if(broadcast != null){
                        broadcastAddress = broadcast;
                        break;
                    }
                }
            }
        }
    } catch (SocketException e) {
        // log the damn exception!
        Logger.getLogger(YourClass.class).error("exception when getting broadcast address", e);
    }
}

答案 1 :(得分:0)

如果在单个实例中存在实现get方法的对象,则在getter方法声明之前的synchronized关键字就足够了。

您也可以使用同步集合(如ConcurrentHashMap)来存储和访问您的数据。

然而,有可能存在更有效的解决方案。与所有多线程同步一样,您必须识别并隔离关键部分。通常临界区越短,代码的速度就越快。

答案 2 :(得分:0)

据我所知,您的代码是线程安全的,因此这里不需要额外的工作。您没有使用可以沿线程共享的共享可变资源,所以在这里应该没有问题。