非线程安全字段不应该是静态的,sonar lint 错误
Non-thread-safe fields should not be static, sonar lint error
嗨,我有这个代码示例。
public class Util implements Serializable {
private static final SimpleDateFormat DATE_KEY_FORMAT = new SimpleDateFormat("yyyyMMdd");
private static final SimpleDateFormat EUS_WS_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
private static final SimpleDateFormat DATETIME_KEY_FORMAT = new SimpleDateFormat("yyyyMMddHHmmssSSS");
public static final String TIME_ZONE_GMT = "GMT";
/**
* Returns date in the format yyyyMMdd
* @return
*/
public static int getyyyyMMdd() {
return Integer.parseInt(DATE_KEY_FORMAT.format(new Date()));
}
public static int getyyyyMMdd(Date date) {
return Integer.parseInt(DATE_KEY_FORMAT.format(date));
}
public static String getyyMMdd(Date dateTime) {
return DATE_KEY_FORMAT.format(dateTime);
}
public static String getyyyyMMddHHmmssSSSCur(Date dateTime) {
return DATETIME_KEY_FORMAT.format(dateTime);
}
如果我从行中删除静态:private static final SimpleDateFormat DATE_KEY_FORMAT = new SimpleDateFormat("yyyyMMdd")
,那么如何以非静态方式访问它?因为它在下面的代码中显示错误:
public static int getyyyyMMdd() {
return Integer.parseInt(DATE_KEY_FORMAT.format(new Date()));
}
任何人都可以告诉我在移除静态后如何访问它吗?提前致谢
SimpleDateFormat
实例不是线程安全的,因此确实不应有并发访问。
您应该使静态方法成为实例方法,因为静态方法无法访问实例成员。
另请注意,如果同时访问这些方法,您将遇到相同的并发问题。因此,在多线程环境中,您应该在每个方法中创建 SimpleDateFormat
实例(这可能很昂贵)或(不太昂贵)在 ThreadLocal
.[=14 中添加 SimpleDateFormat
的单个实例=]
删除 static
不会使其成为线程安全的:可以从不同的线程同时访问实例。
考虑使用 ThreadLocal<SimpleDateFormat>
:
private static final ThreadLocal<SimpleDateFormat> DATE_KEY_FORMAT =
ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyyMMdd"));
然后像这样访问静态方法:
return Integer.parseInt(DATE_KEY_FORMAT.get().format(new Date()));
因为每个线程都有自己的SimpleDateFormat
实例,所以线程之间没有干扰。
但是,在您调用 DATE_KEY_FORMAT.remove()
之前,对 SimpleDateFormat
的突变更改(例如设置时区)将保留在给定线程中。但是,如果您从未像那样对实例进行过更改,则无需担心这一点。
静态字段属于class,而实例变量属于对象。因此,静态字段的值在 class 的所有实例之间共享。因此,如果您尝试从静态上下文中调用实例变量,它将不起作用,因为调用静态方法时该实例可能不存在。
例如,对于某些 class 你调用 util 方法 getyyyMMdd() 而没有实例化实例变量。
public class SomeClass() {
public SomeClass(){}
public printDateInYears() {
System.out.println(Util.getyyyyMMdd());
}
}
访问实例变量的唯一方法是使方法 getyyyyMMdd() 不是静态的。
嗨,我有这个代码示例。
public class Util implements Serializable {
private static final SimpleDateFormat DATE_KEY_FORMAT = new SimpleDateFormat("yyyyMMdd");
private static final SimpleDateFormat EUS_WS_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
private static final SimpleDateFormat DATETIME_KEY_FORMAT = new SimpleDateFormat("yyyyMMddHHmmssSSS");
public static final String TIME_ZONE_GMT = "GMT";
/**
* Returns date in the format yyyyMMdd
* @return
*/
public static int getyyyyMMdd() {
return Integer.parseInt(DATE_KEY_FORMAT.format(new Date()));
}
public static int getyyyyMMdd(Date date) {
return Integer.parseInt(DATE_KEY_FORMAT.format(date));
}
public static String getyyMMdd(Date dateTime) {
return DATE_KEY_FORMAT.format(dateTime);
}
public static String getyyyyMMddHHmmssSSSCur(Date dateTime) {
return DATETIME_KEY_FORMAT.format(dateTime);
}
如果我从行中删除静态:private static final SimpleDateFormat DATE_KEY_FORMAT = new SimpleDateFormat("yyyyMMdd")
,那么如何以非静态方式访问它?因为它在下面的代码中显示错误:
public static int getyyyyMMdd() {
return Integer.parseInt(DATE_KEY_FORMAT.format(new Date()));
}
任何人都可以告诉我在移除静态后如何访问它吗?提前致谢
SimpleDateFormat
实例不是线程安全的,因此确实不应有并发访问。
您应该使静态方法成为实例方法,因为静态方法无法访问实例成员。
另请注意,如果同时访问这些方法,您将遇到相同的并发问题。因此,在多线程环境中,您应该在每个方法中创建 SimpleDateFormat
实例(这可能很昂贵)或(不太昂贵)在 ThreadLocal
.[=14 中添加 SimpleDateFormat
的单个实例=]
删除 static
不会使其成为线程安全的:可以从不同的线程同时访问实例。
考虑使用 ThreadLocal<SimpleDateFormat>
:
private static final ThreadLocal<SimpleDateFormat> DATE_KEY_FORMAT =
ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyyMMdd"));
然后像这样访问静态方法:
return Integer.parseInt(DATE_KEY_FORMAT.get().format(new Date()));
因为每个线程都有自己的SimpleDateFormat
实例,所以线程之间没有干扰。
但是,在您调用 DATE_KEY_FORMAT.remove()
之前,对 SimpleDateFormat
的突变更改(例如设置时区)将保留在给定线程中。但是,如果您从未像那样对实例进行过更改,则无需担心这一点。
静态字段属于class,而实例变量属于对象。因此,静态字段的值在 class 的所有实例之间共享。因此,如果您尝试从静态上下文中调用实例变量,它将不起作用,因为调用静态方法时该实例可能不存在。
例如,对于某些 class 你调用 util 方法 getyyyMMdd() 而没有实例化实例变量。
public class SomeClass() {
public SomeClass(){}
public printDateInYears() {
System.out.println(Util.getyyyyMMdd());
}
}
访问实例变量的唯一方法是使方法 getyyyyMMdd() 不是静态的。