且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

scala.concurrent.ExecutionContext.Implicits.global的行为是什么?

更新时间:2022-10-15 15:14:48

默认



href =http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool-int-> ThreadPool ,其具有与机器上的处理器一样多的线程。合理的默认意味着它在大多数时间对大多数事情有好处。



一个好线程池



首先,理解你只有与机器上的核心一样多的线程。所有其他线程都是所谓的demon线程,它是所有关于使用队列和执行的聪明(在语言/库级别)。



CachedThreadPool:Many短暂的/廉价的任务



你生成的线程池的类型很大程度上取决于它们要执行的操作。对于很多短暂的动作(比如数据库查询),你会去一个缓存线程池。



因为每个单独的任务相对便宜,但产生一个新的线程是昂贵的,则***使用 CachedThreadPool


$ b

FixedThreadPool:长时间运行/昂贵的任务 $ b

与上述相反,对于非常昂贵的操作,您可能想限制一次运行的线程数量,原因如下:内存,性能等。



ForkJoinPool:Divide et impera



这种类型的池在需要执行大型计算时非常有用,将其划分为个体工作人员可以计算的更小的位。



列表继续。底线,Scala给你之间的所有上述。具体来说,Scala尝试创建一个ForkJoinPool,如果第一个失败则默认为ThreadPoolExecutor。

  try {
new ForkJoinPool (
desiredParallelism,
threadFactory,
uncaughtExceptionHandler,
true)//异步所有方式baby
} catch {
case NonFatal(t)=> ;
System.err.println(无法为默认的ExecutionContext创建ForkJoinPool,回退到ThreadPoolExecutor)
t.printStackTrace(System.err)
val exec = new ThreadPoolExecutor(
requiredParallelism,
desiredParallelism,
5L,
TimeUnit.MINUTES,
new LinkedBlockingQueue [Runnable],
threadFactory

exec。 allowCoreThreadTimeOut(true)
exec
}

}



完整 列表。


The documentation for scala.concurrent.ExecutionContext.Implicits.global on the ExecutionContext trait reads:

It is possible to simply import scala.concurrent.ExecutionContext.Implicits.global to obtain an implicit ExecutionContext. This global context is a reasonable default thread pool

What does it mean by "reasonable default"?

Default

It's a fixed size ThreadPool, which has as many threads as the processors on the machine. A reasonable default means it's good for most things most of the time.

What a "good" thread pool is

First, it's important to understand you only have as many threads as the cores on the machine. All other threads are so called demon threads and it's all about being smart with queue-ing and executing.(at language/library level).

CachedThreadPool: Many short lived/cheap tasks

The type of thread pools you spawn vastly depend on the actions they are mean to perform. For a lot of short lived actions(say database queries), you would go a with a cached thread pool.

Because each individual task is relatively cheap but spawning a new thread is expensive, you are better off with a CachedThreadPool.

FixedThreadPool: Long running/expensive tasks

In contrast with the above, for very expensive operations, you probably want to limit the amount of threads running at one time, for various reasons: memory, performance etc.

ForkJoinPool: Divide et impera

This type of pool is useful when you need to perform a very large computation, but you can divide it into smaller bits individual workers can compute.

The list goes on and on. Bottom line, Scala gives you something in between all of the above. Specifically, Scala tries to create a ForkJoinPool and defaults to a ThreadPoolExecutor if the first fails.

try {
  new ForkJoinPool(
    desiredParallelism,
    threadFactory,
    uncaughtExceptionHandler,
    true) // Async all the way baby
} catch {
  case NonFatal(t) =>
    System.err.println("Failed to create ForkJoinPool for the default ExecutionContext, falling back to ThreadPoolExecutor")
    t.printStackTrace(System.err)
    val exec = new ThreadPoolExecutor(
      desiredParallelism,
      desiredParallelism,
      5L,
      TimeUnit.MINUTES,
      new LinkedBlockingQueue[Runnable],
      threadFactory
    )
    exec.allowCoreThreadTimeOut(true)
    exec
}

}

The full list here.