我将在Scala中学习并发编程,并遇到以下问题:
但是,在当前版本的Scala中,如果没有同步,则无法共享某些被认为是不可变的集合,例如List和Vector.虽然它们的外部API不允许您修改它们,但它们包含非最终字段.
提示:即使对象看起来是不可变的,也总是使用适当的同步来共享线程之间的任何对象.
来自Aleksandar Prokopec的Scala学习并发编程,第2章结尾(第58页),Packt Publishing,2014年11月.
那可能是对的吗?
我的工作假设一直是在Scala库数据结构中描述为不可变的任何内部可变性(实现懒惰,缓存等)都是幂等的,这样在糟糕的竞争中可能发生的最坏情况就是不必要地重复工作.这位作者似乎认为,通过并发访问不可变结构可能会危害正确性.真的吗?我们真的需要同步对列表的访问吗?
我转向不可变重型风格的大部分原因都是为了避免同步以及它所带来的潜在争用开销.要了解Scala的核心"不可变"数据结构无法避免同步,这将是一件不愉快的大事.这位作者是否过于保守?
Scala的集合文档包括以下内容:
scala.collection.immutable包中的集合保证对每个人都是不可变的.这样的集合在创建后永远不会改变.因此,您可以依赖于在不同时间点重复访问相同集合值将始终生成具有相同元素的集合的事实.
这并不能说它们对多个线程的并发访问是安全的.有没有人知道他们是(或不是)的权威声明?
明智与否,我正在编写一种方法,我只想接受Scala单例,即通过"对象"实现的对象,而不是类或特性的构造实例.它应该接受任何类型的Scala单例,因此"MySingleton.type"不会这样做.
我遇到了一个非常奇怪的构造"scala.Singleton",它没有在api文档中记录,但似乎可以解决这个问题:
scala> def check( obj : Singleton ) = obj
check: (obj: Singleton)Singleton
scala> check( Predef )
res0: Singleton = scala.Predef$@4d3e9963
scala> check ( new java.lang.Object() )
<console>:9: error: type mismatch;
found : java.lang.Object
required: Singleton
check ( new java.lang.Object() )
scala> check( Map )
res3: Singleton = scala.collection.immutable.Map$@6808aa2d
scala> check( Map.empty[Any,Any] )
<console>:9: error: type mismatch;
found : scala.collection.immutable.Map[Any,Any]
required: Singleton
check( Map.empty[Any,Any] )
Run Code Online (Sandbox Code Playgroud)
但是,相当莫名其妙地(对我来说),字符串文字被接受为单例,而显式构造的字符串不是:
scala> check( "foo" )
res7: Singleton = foo
scala> check( new String("foo") ) …Run Code Online (Sandbox Code Playgroud) 我曾怀疑Scala的类型系统已经内置了这个支持,但是在浏览了Numeric,Fractional和FractionalProxy后,我无法找到方法.
我想抽象地定义一个数值模型,这样它可以使用Doubles,Floats和BigDecimals,具有Float和Double的特化.
我似乎已经使它工作,但需要付出很多努力和样板.首先,是否(请?)一个较少的kludgey,更简洁的方式?其次,尽管视图边界的隐式转换,我使用值类型是否有效保持专用原始类型不被包装?
非常感谢.
object Model {
sealed trait Value[T] extends Any { //contains all the operations I use
def value : T;
def + ( other : Value[T]) : Value[T];
def / ( other : Value[T]) : Value[T];
def - ( other : Value[T]) : Value[T];
def * ( other : Value[T]) : Value[T];
def < ( other : Value[T]) : Boolean;
def unary_- : Value[T];
def abs : Value[T];
}
implicit def unwrap[T]( wrapped : Value[T]) : T …Run Code Online (Sandbox Code Playgroud) 假设我在 Postgres 9.4 中有下表:
a | b
---+---
1 | 2
3 | 1
2 | 3
1 | 1
Run Code Online (Sandbox Code Playgroud)
如果我跑
select array_agg(a) as a_agg, array_agg(b) as b_agg from foo
Run Code Online (Sandbox Code Playgroud)
我得到我想要的
a_agg | b_agg
-----------+-----------
{1,3,2,1} | {2,1,3,1}
Run Code Online (Sandbox Code Playgroud)
两个数组的顺序是一致的:每个数组的第一个元素来自同一行,第二个和第三个也是如此。我实际上并不关心数组的顺序,只关心它们在列之间保持一致。
这似乎很自然地“就这样发生了”,而且似乎确实如此。但它可靠吗?通常,除非指定 ORDER BY 子句,否则 SQL 事物的顺序是未定义的。完全有可能让 postgres 生成不一致的配对,其中包含不一致的 ORDER BY 子句array_agg(需要一些明显适得其反的额外工作):
select array_agg(a order by b) as agg_a, array_agg(b order by a) as agg_b from foo;
Run Code Online (Sandbox Code Playgroud)
产量
agg_a | agg_b
-----------+-----------
{3,1,1,2} | {2,1,3,1}
Run Code Online (Sandbox Code Playgroud)
这不再一致。第一个数组元素 3 和 2 并非来自同一原始行。 …
我的一些构建和插件使用私有部署凭据(有时从文件系统读取,有时通过 输入并保留在内存中InteractionService)。
虽然这可能是过度偏执,但我尽量小心地尽量减少使用私人信息的软件的攻击面,并且在这些构建中不必要地运行服务器,即使是在 localhost 或 UNIX 套接字上,也感觉很不卫生。
我已经寻找了一个可以在插件中设置的设置,该设置将禁用服务器启动,除非被构建覆盖。到目前为止还没有发现类似的东西。有这样的设定吗?
非常感谢!
更新:在 Eugene Yokota 的帮助下,从 sbt 1.1.1 开始,现在有一个布尔值autoStartServer设置。构建和插件可以通过设置来防止服务器自动启动autoStartServer := false。(startServer如果愿意,用户仍然可以通过运行手动启动服务器。)
我总是将case类的构造函数参数理解为定义公共vals.
但是,当我反映字段时,isPublic方法出现错误.有什么想法吗?
scala> class Test( val name : String, val num : Int )
defined class Test
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> val tpe = typeOf[Test]
tpe: reflect.runtime.universe.Type = Test
scala> def checkValVisibility( t : Type ) = {
| t.members
| .filter( _.isTerm )
| .map( _.asTerm )
| .filter( _.isVal )
| .map( memb => "Val " + memb.name.toString.trim + " is public? " + memb.isPublic )
| .mkString("\n")
| }
checkValVisibility: (t: reflect.runtime.universe.Type)String
scala> checkValVisibility( tpe …Run Code Online (Sandbox Code Playgroud) 假设我试图“抽象执行”:
import scala.language.higherKinds
class Operator[W[_]]( f : Int => W[Int] ) {
def operate( i : Int ) : W[Int] = f(i)
}
Run Code Online (Sandbox Code Playgroud)
现在,我可以定义一个Operator[Future]或Operator[Task]等。例如...
import scala.concurrent.{ExecutionContext,Future}
def futureSquared( i : Int ) = Future( i * i )( ExecutionContext.global )
Run Code Online (Sandbox Code Playgroud)
以REPL风格...
scala> val fop = new Operator( futureSquared )
fop: Operator[scala.concurrent.Future] = Operator@105c54cb
scala> fop.operate(4)
res0: scala.concurrent.Future[Int] = Future(<not completed>)
scala> res0
res1: scala.concurrent.Future[Int] = Future(Success(16))
Run Code Online (Sandbox Code Playgroud)
万岁!
但是我也可能想要一个简单的同步版本,所以我在某个地方定义
type Identity[T] = T
Run Code Online (Sandbox Code Playgroud)
我可以定义一个同步运算符...
scala> def square( …Run Code Online (Sandbox Code Playgroud) Scala在Java的类型系统上叠加了一个非常优雅的类层次结构,从顶部的Any,到AnyRef和AnyVal分别覆盖Java的对象和基元,然后最终收敛,将引用类型折叠到Null,将所有类型折叠到Nothing上.据我所知,没有什么是一切的子类型; Null AnyRef/java.lang.Object的所有子类型的子类型.[见http://www.scala-lang.org/node/128 ]
但是,似乎存在一些不规则性,一些地方不能简单地将所有Scala类型视为无缝类型层次结构的元素.我觉得这很令人厌烦,想要了解我可能感到惊讶的地方.
到目前为止,我知道一些违规行为:
1)虽然Null是AnyRef的子类型,但调用null.isInstanceOf [AnyRef](或AnyRef的其他子类型)会返回false.我怀疑这被选择与Java的instanceof运算符的行为一致.
2)无论方差注释如何,一切都与Nothing协变.如果我有一个方法返回一个没有标记协变的类型T,我可以覆盖该方法返回类型Nothing.[注意:这个说法有误,请参阅下面的答案和评论!]
3)我不能将isInstanceOf应用于AnyVal类型[请参阅为什么AnyVal不能用于isInstanceOf检查?以及如何测试AnyVal的值?]
4)是违法的问是否东西isInstanceOf [空],这是要求完全一致的东西(虽然不是特别必要的,因为"myVar的== NULL"将给出相同的答案)
在Scala的类型层次结构中是否存在其他不规则或特殊情况的示例?我觉得这些值得学习和理解,以避免不受欢迎的惊喜.
这感觉非常基本; 对不起,我很抱歉.
考虑
trait Foo[+T] { def t : T }
trait Bar[+S,+T] extends Foo[T] { def s : S }
trait Baz[+S,T] extends Foo[T] { def s : S }
Run Code Online (Sandbox Code Playgroud)
Foo中T的协方差是否自动适用于Baz,即使Baz中的T没有标记为协变?Bar和Baz的行为会有任何有意义的区别吗?
(四处游戏,这两种形式似乎很难区分.如果它们相同,那么Baz形式不会发出警告或发出错误信号就会感觉很脏,因为单独看Baz你会期望T不会变形.)
Jetty在HttpClient启动时启动线程,似乎产生了相当多的线程.我对此感到有些惊讶,因为我认为nio基于网络的一种优点是通过线程多路复用对话.控制使用的线程数很容易HttpClient.setExecutor(...),但我不确定如何考虑应该需要多少线程.每个同时的HTTP请求库是否需要一个线程,HttpURLConnection可能吗?它是否在某种程度上复用?
我正在定义一个在我的应用程序中长期存在的API客户端,并且我正在尝试平衡保持较小的占用空间以及实现良好的并发性能.
非常感谢任何见解.