Scala中的IO操作及ArrayBuffer线程安全问题
时间:2022-07-23
本文章向大家介绍Scala中的IO操作及ArrayBuffer线程安全问题,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
通过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长度为16,但是size0已经大于16,并且array没有及时扩容时,就会报索引越界。
所以,在并发环境下,要注意调用该方法时的线程安全问题,比如利用synchronized做锁处理。
这里只是以ArrayBuffer为例,对于Scala中其他的集合使用时也要注意,防止类似问题的出现影响程序的正常运行。
- Python文学化编程 - Jupyter notebook使用和插件拓展
- PoisonCake(毒蛋糕):内置于手机ROM的恶意代码模块
- Spring+SpringMVC+MyBatis整合
- Python之numpy数组学习(五)——广播
- WordPress再悲剧:WPcache-Blogger感染事件影响五万WordPress网站
- 浅谈神经机器翻译
- 窃取Facebook用户信息:利用Android同源策略漏洞的恶意应用被发现
- 关于React Native 安卓首屏白屏优化
- 浅谈spring security 403机制一、无权限访问二、匿名访问三、有权限访问原因机制指定AccessDeniedHandler指定error-page情景原因结论
- Python之numpy数组学习(二)
- Intent 属性详解(上)
- 复仇行动:Notepad++官网被圣战组织黑了
- 四大组件的纽带——Intent
- 利用HTC One漏洞破解手机PIN密码
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法