Spark UDF线程安全

时间:2016-04-13 07:52:22

标签: scala apache-spark concurrency

我使用Spark来获取包含日期列的数据框,并创建3个新列,其中包含列中日期与今天之间的天,周和月的时间。

我关心的是使用SimpleDateFormat,它不是线程安全的。通常没有Spark这样就可以了,因为它是一个局部变量,但是使用Spark的懒惰评估,在多个UDF上共享一个SimpleDateFormat实例可能会导致问题吗?

def calcTimeDifference(...){
    val sdf = new SimpleDateFormat(dateFormat)

    val dayDifference = udf{(x: String) => math.abs(Days.daysBetween(new DateTime(sdf.parse(x)), presentDate).getDays)}
    output = output.withColumn("days", dayDifference(myCol))

    val weekDifference = udf{(x: String) => math.abs(Weeks.weeksBetween(new DateTime(sdf.parse(x)), presentDate).getWeeks)}
    output = output.withColumn("weeks", weekDifference(myCol))

    val monthDifference = udf{(x: String) => math.abs(Months.monthsBetween(new DateTime(sdf.parse(x)), presentDate).getMonths)}
    output = output.withColumn("months", monthDifference(myCol))
}

1 个答案:

答案 0 :(得分:0)

众所周知, SimpleDateFormat 不是线程安全的。

因此,如果您需要,我更喜欢这种方法在Spark中使用 SimpleDateFormat

import java.text.SimpleDateFormat
import java.util.SimpleTimeZone

/**
  * Thread Safe SimpleDateFormat for Spark.
  */
object ThreadSafeFormat extends ThreadLocal[SimpleDateFormat] {

  override def initialValue(): SimpleDateFormat = {
    val dateFormat = new SimpleDateFormat("yyyy-MM-dd:H")
    // if you need get UTC time, you can set UTC timezone
    val utcTimeZone = new SimpleTimeZone(SimpleTimeZone.UTC_TIME, "UTC")
    dateFormat.setTimeZone(utcTimeZone)
    dateFormat
  }

}

然后使用ThreadSafeFormat.get()来获取线程安全的SimpleDateFormat以执行任何操作。