使用play
,我的控制器调用Foo
服务,对象。此对象仅使用val
和immutable data structures
,将由多个客户端调用。
当我的Controller在多个线程中调用Foo.doQuery()
时,会发生什么?
如果客户1拨打电话执行Foo.doQuery()
,客户2对Foo.doQuery()
的通话是否必须等待?
我很好奇我是否应该为Foo
的每个实例创建一个新类,但我想知道Scala单例会发生什么,仅使用val
,多线程环境。
答案 0 :(得分:10)
不,Scala对象并不意味着锁定(在java中同步),因此客户端2不必等待。如果您没有明确地向代码添加锁,客户端1,客户端2和客户端n都可以同时运行。
想想
object MyObject { ... }
作为
class MyClass(..) { ... }
lazy val MyObject = new MyClass(..)
可以通过“同步”来应用锁定。功能如下:
def doQuery = synchronized {
..
..
}
==编辑==
对于注释中的问题,线程(或调用)堆栈和变量共享与使用不可变引用和/或不可变数据结构的控制器无关。重要的是定义变量的位置。如果在方法(方法变量)中定义变量(无论是val还是var),那么每次调用该方法时,该变量都是为调用线程创建的。另一方面,如果在类或对象级别(实例变量)定义变量,则对实例方法的所有调用始终共享相同的实例变量。
在您的情况下,我认为您可以将控制器实现为单例对象,因为不可变引用和数据结构很好..不可变。如果他们共享与否则无关紧要。
答案 1 :(得分:0)
为说明@harp seal pup的答案,这是带有输出的示例演示,
我们可以观察到可变变量myname
受每个正在运行的线程的影响。
但是不可变的val thname
不会影响或锁定每个线程。
object ObjectMultiThreadingTest {
def main(args: Array[String]): Unit = {
for (x <- 1 to 5) {
var thread = new MyThread()
thread.setName("Thread number :" + x.toString)
thread.start()
}
}
class MyThread extends Thread {
override def run(): Unit = {
Singleton.myname = this.getName
Singleton.call(this.getName)
}
}
object Singleton {
var myname = "Singleton"
def call(threadName: String): Unit = {
val thName = threadName
val random = new Random
for (i <- 1 to 5) {
println("My Name is set by " + myname)
val sleeptime = random.nextInt(1000)
println(
"But, I am now running " + thName + ", sleeping for " + sleeptime
)
Thread.sleep(sleeptime)
}
}
}
}
输出:
My Name is set by Thread number :5
My Name is set by Thread number :5
My Name is set by Thread number :5
But, I am now running Thread number :3, sleeping for 498
My Name is set by Thread number :5
My Name is set by Thread number :5
But, I am now running Thread number :5, sleeping for 968
But, I am now running Thread number :4, sleeping for 232
But, I am now running Thread number :2, sleeping for 562
But, I am now running Thread number :1, sleeping for 204
My Name is set by Thread number :5
But, I am now running Thread number :1, sleeping for 315
My Name is set by Thread number :5
But, I am now running Thread number :4, sleeping for 100
My Name is set by Thread number :5
But, I am now running Thread number :4, sleeping for 749
My Name is set by Thread number :5
But, I am now running Thread number :3, sleeping for 66
My Name is set by Thread number :5
But, I am now running Thread number :1, sleeping for 4
My Name is set by Thread number :5
But, I am now running Thread number :1, sleeping for 332
My Name is set by Thread number :5
But, I am now running Thread number :2, sleeping for 899
My Name is set by Thread number :5
But, I am now running Thread number :3, sleeping for 679
My Name is set by Thread number :5
But, I am now running Thread number :1, sleeping for 849
My Name is set by Thread number :5
But, I am now running Thread number :5, sleeping for 157
My Name is set by Thread number :5
But, I am now running Thread number :4, sleeping for 694
My Name is set by Thread number :5
But, I am now running Thread number :5, sleeping for 864
My Name is set by Thread number :5
But, I am now running Thread number :3, sleeping for 591
My Name is set by Thread number :5
But, I am now running Thread number :2, sleeping for 702
My Name is set by Thread number :5
But, I am now running Thread number :4, sleeping for 339
My Name is set by Thread number :5
But, I am now running Thread number :3, sleeping for 959
My Name is set by Thread number :5
But, I am now running Thread number :5, sleeping for 443
My Name is set by Thread number :5
But, I am now running Thread number :2, sleeping for 522
My Name is set by Thread number :5
But, I am now running Thread number :5, sleeping for 368
My Name is set by Thread number :5
But, I am now running Thread number :2, sleeping for 851