Scala中的IO操作及ArrayBuffer線程安全問題
VSole2022-07-31 10:07:22
通過Scala對文件進行讀寫操作在實際業務中應用也比較多,這里介紹幾種常用的方式,直接上代碼:
1.從文件中讀取內容
object Main {
def loadData(): Array[String] = {
var bs: BufferedSource = null
var in: InputStream = null
try {
in = Main.getClass.getClassLoader.getResourceAsStream("data.txt")
if (in == null) {
in = new FileInputStream(new File("data.txt"))
}
bs = new BufferedSource(in)
bs.getLines().toArray
} finally {
bs.close()
}
}
//直接通過scala.io.Source進行讀取
def testSource(): Unit = {
Source.fromFile("data.txt").foreach(println)
}
}
2.向文件中寫內容
def write(): Unit ={
//調用的就是java中的io類
val writer = new PrintWriter(new File("write.txt" ))
writer.write("scala write")
writer.close()
}
除了讀寫方式,也可以從上面的“屏幕處理”上讀取用戶輸入的指令來程序:
import scala.io. StdIn
def printIn(): Unit = {
print("please enter number :")
val line = StdIn.readLine()
println(s"number is : $line")
}
相信使用 Scala 進行應用開發時,ArrayBuffer 使用該問題。但是ArrayBuffer 進行添加元素時,使用方法:+=。方法是線程安全的,如果在多線程環境中使用該方法,例如,很容索引報越界異常。
模擬多向異向定義的ArrayBuffer中插入100個元素:
def arrBuffer(): Unit = {
//默認初始容量為16
val arrayBuffer = new ArrayBuffer[Int]()
val executors = Executors.newFixedThreadPool(100)
for (i <- 1 to 100) {
executors.execute(new Runnable {
override def run(): Unit = {
arrayBuffer += i
}
})
}
executors.shutdown()
}
執行上述程序,報出類似以下的索引越界問題:
java.lang.ArrayIndexOutOfBoundsException: 32
at scala.collection.mutable.ArrayBuffer.$plus$eq(ArrayBuffer.scala:85)
at Main$$anonfun$main$1$$anon$1.run(Main.scala:24)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
再來看看ArrayBuffer的+=實現源碼:
//初始容量
protected def initialSize: Int = 16
//array默認長度為16
protected var array: Array[AnyRef] = new Array[AnyRef](math.max(initialSize, 1))
//元素個數,默認0
protected var size0: Int = 0
def +=(elem: A): this.type = {
ensureSize(size0 + 1)
array(size0) = elem.asInstanceOf[AnyRef]
size0 += 1
this
}
val arrayBuffer = new ArrayBuffer[Int](初始容量為16),索引容量情況:下當array長度為1,但大小0已經大于16,并且array沒有及時擴展時,會報越界。
所以,在方法環境下,要注意調用該線程時的安全問題,比如利用同步做鎖處理。
這里只是以 ArrayBuffer 為例,對于 Scala 中其他的集合使用時也要注意,類似的防止出現的問題會影響程序的正常運行。
VSole
網絡安全專家