![](/img/trans.png)
[英]How many concurrent tasks in one executor and how Spark handles multithreading among tasks in one executor?
[英]How Spark tasks in the same executor share variables (NumberFormatException with SimpleDateFormat)?
火花文檔說
默認情況下,當Spark作為一組任務在不同節點上並行運行一個函數時,它會將函數中使用的每個變量的副本傳送給每個任務。
如果創建Java SimpleDateFormat
並將其用於RDD操作中,則會出現NumberFormatException: multiple points
異常。
我知道SimpleDateFormat
不是線程安全的。 但是正如spark docs所說,此SimpleDateFormat
對象已復制到每個任務,因此不應有多個線程訪問此對象。
我推測一個執行程序中的所有任務共享同一個SimpleDateFormate
對象,對嗎?
該程序打印相同的對象java.text.SimpleDateFormat@f82ede60
object NormalVariable {
// create dateFormat here doesn't change
// val dateFormat = new SimpleDateFormat("yyyy.MM.dd")
def main(args: Array[String]) {
val dateFormat = new SimpleDateFormat("yyyy.MM.dd")
val conf = new SparkConf().setAppName("Spark Test").setMaster("local[*]")
val spark = new SparkContext(conf)
val dates = Array[String]("1999.09.09", "2000.09.09", "2001.09.09", "2002.09.09", "2003.09.09")
println(dateFormat)
val resultes = spark.parallelize(dates).map { i =>
println(dateFormat)
dateFormat.parse(i)
}.collect()
println(resultes.mkString(" "))
spark.stop()
}
}
如您所知, SimpleDateFormat
不是線程安全的。
如果Spark在每個執行器上使用單個核心( --executor-cores 1
),那么一切都應該正常工作。 但是,一旦您為每個執行程序配置了多個內核,您的代碼就會立即運行多線程, SimpleDateFormat
會同時由多個Spark任務共享,並且很可能破壞數據並引發各種異常。
要解決此問題,可以使用與非Spark代碼相同的方法之一,即ThreadLocal
,以確保每個線程獲得一個SimpleDateFormat
副本。
在Java中,這看起來像:
public class DateFormatTest {
private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>(){
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyyMMdd");
}
};
public Date convert(String source) throws ParseException{
Date d = df.get().parse(source);
return d;
}
}
並且Scala中的等效代碼工作原理相同-在此處顯示為spark-shell
會話:
import java.text.SimpleDateFormat
object SafeFormat extends ThreadLocal[SimpleDateFormat] {
override def initialValue = {
new SimpleDateFormat("yyyyMMdd HHmmss")
}
}
sc.parallelize(Seq("20180319 162058")).map(SafeFormat.get.parse(_)).collect
res6: Array[java.util.Date] = Array(Mon Mar 19 16:20:58 GMT 2018)
因此,您將在作業class
或object
的頂層定義ThreadLocal
,然后調用df.get
在RDD操作中獲取SimpleDateFormat
。
看到:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.