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
网络安全专家