Java 处理一次可由多个线程访问的通用方法的最佳设计模式

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

我试图创建一个静态方法,该方法一次可由不同类的多个方法访问

由于它是静态的,它会被锁定,我会得到不同的结果和性能问题

是否有更好的方法使这些方法一次可供多个方法访问

在Spring框架中有更好的方法来处理这个问题吗

  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;
}