Java:多线程复杂Getter
我有一个get方法,它返回一个非原语类型,并且应该是线程安全的 功能描述 我有一个单独线程上的操作。此操作需要IP地址,并使用我自己的getter方法从其他类获取它(因为我必须进行一些IP地址计算)。getter返回一个Java:多线程复杂Getter,java,multithreading,Java,Multithreading,我有一个get方法,它返回一个非原语类型,并且应该是线程安全的 功能描述 我有一个单独线程上的操作。此操作需要IP地址,并使用我自己的getter方法从其他类获取它(因为我必须进行一些IP地址计算)。getter返回一个InetAddress 代码示例 // This is called in a separate thread. // How can I make Utility.getMyIp() thread-safe? InetAddress myIp = Utility.getMyIp
InetAddress
代码示例
// This is called in a separate thread.
// How can I make Utility.getMyIp() thread-safe?
InetAddress myIp = Utility.getMyIp();
问题
关于IP地址getter方法,我需要注意什么?我需要使用另一个线程中的方法。我必须使它同步吗
如果您需要更多信息,请咨询
PS:也有其他线程提出类似的问题,但我发现的那些线程只讨论基本数据类型,应该足够使用volatile关键字。这里我需要返回一个类型InetAddress
编辑:添加代码
// This is called in a separate thread.
// How can I make Utility.getMyIp() thread-safe?
InetAddress myIp = Utility.getMyIp();
这是正在进行的工作(它可能不会在所有情况下都工作,并且不是完成的代码)
/**
*获取IPv4的广播地址。
*@返回
*@SocketException
*/
公共静态InetAddress getBroadcastAddress4(){
//Todo:检查其他可能性
setProperty(“java.net.preferIPv4Stack”,“true”);
//初始化
InetAddress广播地址=null;
试一试{
枚举接口=NetworkInterface.getNetworkInterfaces();
while(interfaces!=null&&interfaces.hasMoreElements()){
NetworkInterface currentInterface=interfaces.nextElement();
如果(!currentInterface.isLoopback()){
for(InterfaceAddress地址:currentInterface.GetInterfaceAddress()){
InetAddress广播=address.getBroadcast();
如果(广播!=null){
广播地址=广播;
打破
}
}
}
}
}捕获(SocketException e){
e、 printStackTrace();
}
返回地址;
}
如果实现get
方法的对象存在于单个实例中,则在getter方法声明之前添加一个synchronized
关键字就足够了
您还可以使用同步收集(如)来存储和访问数据
然而,有可能存在更有效的解决方案。与所有多线程同步一样,您必须识别并隔离关键部分。通常,临界段越短,代码的速度就越好。据我所知,您的代码是线程安全的,因此这里不需要额外的工作。您没有使用可以沿线程共享的共享可变资源,因此这里应该没有问题 代码是线程安全的,无需进一步修改 您还可以将此方法的结果存储到一个变量中,并执行一次实际计算,因为结果在程序运行期间不太可能更改。延迟初始化变量,或者使用
静态{}
代码块在类加载时初始化它。代码可能如下所示:
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);
}
}
InetAddress广播地址;
公共静态InetAddress getBroadcastAddress4(){
返回地址;
}
静止的{
setProperty(“java.net.preferIPv4Stack”,“true”);
试一试{
枚举接口=NetworkInterface.getNetworkInterfaces();
while(interfaces!=null&&interfaces.hasMoreElements()){
NetworkInterface currentInterface=interfaces.nextElement();
如果(!currentInterface.isLoopback()){
for(InterfaceAddress地址:currentInterface.GetInterfaceAddress()){
InetAddress广播=address.getBroadcast();
如果(广播!=null){
广播地址=广播;
打破
}
}
}
}
}捕获(SocketException e){
//记录这个该死的异常!
Logger.getLogger(YourClass.class).error(“获取广播地址时异常”,e);
}
}
是getMyIp
静态吗?是的,它是静态的,或者如果它更好(相对于多线程),我也可以实例化实用程序,但现在它是静态的。我一直认为读取是线程安全的…@antoniosss,这取决于。如果您有一个简单的读取基元数据类型的read,那么它可能是(不完全是!)。问题是我的读数做了一些计算,不是原子的。数据可能会更改,并且可能会并发访问我正在使用的不同类。然后它不会被读取-这就是我编写的wy。谢谢,get方法存在于单个实例中,但在计算IP地址时有一些逻辑。它使用的是来自其他类的其他方法,这些方法来自Java框架(不是我自己的类)。只需发布getMyIp()
方法,我们就可以说得更多。我将发布该方法,但我认为如果您知道它是一个使用其他库中不同对象和类的复杂方法,就足够了。使问题变得更复杂。我正在设置系统属性,我正在使用NetworkInterface类,该类包含接口枚举(在迭代时可能会更改)。如果你问我的话,这里有共享的可变资源。1)你在类加载过程中设置了系统道具-只会发生一次。2) 否,此集合不会更改。任何对NetworkInterface.getNetworkInterfaces()
的连续调用都会产生不同的结果,但onece返回的集合不会改变。3) 我不是在问你,我是在告诉你,因为你显然把可变资源和不同的值混淆了。我在get方法中设置了系统属性(这是静态的)。我想每次有人打电话来都会安排好的,我有什么事吗?还是说我应该换个地方?大约2号