Java 处理一次可由多个线程访问的通用方法的最佳设计模式
我试图创建一个静态方法,该方法一次可由不同类的多个方法访问 由于它是静态的,它会被锁定,我会得到不同的结果和性能问题 是否有更好的方法使这些方法一次可供多个方法访问 在Spring框架中有更好的方法来处理这个问题吗Java 处理一次可由多个线程访问的通用方法的最佳设计模式,java,multithreading,spring,design-patterns,Java,Multithreading,Spring,Design Patterns,我试图创建一个静态方法,该方法一次可由不同类的多个方法访问 由于它是静态的,它会被锁定,我会得到不同的结果和性能问题 是否有更好的方法使这些方法一次可供多个方法访问 在Spring框架中有更好的方法来处理这个问题吗 public class TestUtil { public static SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd"); public static java.sql.Date getLastDay
public class TestUtil {
public static SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
public static java.sql.Date getLastDayOfMonth(String month,intyear)
throws ParseException{
switch (month) {
case "jan":
return new java.sql.Date(f.parse(year+"-1-31").getTime());
case "feb": if(isLeapYear(year))
return new java.sql.Date(f.parse(year+"-2-29").getTime());
else
return new java.sql.Date(f.parse(year+"-2-28").getTime());
case "mar":
return new java.sql.Date(f.parse(year+"-3-31").getTime());
case "apr":
return new java.sql.Date(f.parse(year+"-4-30").getTime());
case "may":
return new java.sql.Date(f.parse(year+"-5-31").getTime());
case "jun":
return new java.sql.Date(f.parse(year+"-6-30").getTime());
case "jul":
return new java.sql.Date(f.parse(year+"-7-31").getTime());
case "aug":
return new java.sql.Date(f.parse(year+"-8-31").getTime());
case "sep":
return new java.sql.Date(f.parse(year+"-9-30").getTime());
case "oct":
return new java.sql.Date(f.parse(year+"-10-31").getTime());
case "nov":
return new java.sql.Date(f.parse(year+"-11-30").getTime());
case "dec":
return new java.sql.Date(f.parse(year+"-12-31").getTime());
default: month = "Invalid month";
return null;
}
}
}
如果绝对需要一个静态字段,请将其更改为
ThreadLocal
,在您的情况下,public static ThreadLocal f=new ThreadLocal()代码>,或者,如果没有,请在静态方法中将字段更改为局部变量,这样您就没事了。
你的技术太差了
答复
使用Spring将实例化对象注入到类中。
默认类型为singleton,
这就是你想要的。
不要在实用程序方法中存储任何状态。
使用非静态方法
不要解析字符串来查找日期,
而是使用Calendar类。
同样,您也可以不使用静态SimpleDataFormat,而只使用本地。
下面是一些代码(使用静态SimpleDataFormat)
为安全起见,您可以做的最好的事情之一是消除多线程的状态更改,最确定的方法是使用不可变对象
它经常被忽略,但是SimpleDataFormat
具有可变状态(它跟踪调用之间的解析操作状态)。因此,正如您所发现的,从多个线程同时使用它是行不通的
寻找替代方案以消除共享状态。在本例中,很简单:只需在Java 8中使用改进的日期和时间API:
private static final DateTimeFormatter f;
static {
DateTimeFormatterBuilder b = new DateTimeFormatterBuilder();
b.parseCaseInsensitive();
b.parseDefaulting(ChronoField.DAY_OF_MONTH, 1);
b.appendPattern("uuuuMMM");
f = b.toFormatter(Locale.US); /* f is an immutable object! */
}
public static LocalDate getLastDayOfMonth(String month, int year)
{
LocalDate first = LocalDate.parse(year + month, f);
LocalDate last = first.with(TemporalAdjusters.lastDayOfMonth());
return last;
}
是什么让您认为多线程是这里的性能瓶颈?顺便说一句,SimpleDataFormat:“日期格式不同步。建议为每个线程创建单独的格式实例。如果多个线程同时访问一种格式,则必须在外部同步。”如果我必须返回java.sql.Date而不是java.util.Date,该怎么办?我建议您阅读java.sql.Date和java.util.Date类的API文档。可以用很长的毫秒来构造java.sql.Date。java.util.Date有一个以毫秒为单位返回日期值的方法(getDate())。returnValue=newjava.sql.Date(calendar.getTime().getTime());私有静态最终SimpleDataFormat dateFormat=新SimpleDataFormat(“yyyy-MM-dd”);这不是线程安全的,对吗?当仅用于格式化时,我相信SimpleDataFormat是线程安全的。考虑阅读你所引用的答案。解析和格式化,信不信由你,不同的方法。谢谢,如果我必须使用Java7,我必须在Java.ql日期中返回日期?@ CalkoKi,然后每次调用该方法时,只创建一个新的本地实例:<代码>日历>代码>。或者使用Joda Time.ThreadLocal对象和局部变量存储在堆栈内存中。但是,如果希望线程之间共享状态(原子性),则需要另一种方法。
private static final DateTimeFormatter f;
static {
DateTimeFormatterBuilder b = new DateTimeFormatterBuilder();
b.parseCaseInsensitive();
b.parseDefaulting(ChronoField.DAY_OF_MONTH, 1);
b.appendPattern("uuuuMMM");
f = b.toFormatter(Locale.US); /* f is an immutable object! */
}
public static LocalDate getLastDayOfMonth(String month, int year)
{
LocalDate first = LocalDate.parse(year + month, f);
LocalDate last = first.with(TemporalAdjusters.lastDayOfMonth());
return last;
}