1) Determining the Number of Threads
最少最少: Runtime.getRuntime().availableProcessors();
Number of threads = (Number of Available Cores) / (1 - Blocking Coefficient)
2) Determining the Number of Parts - Divide and Conquer 重于计算的, Blocking Coefficient is 1.
It turns out that keeping the cores busy on the problem is more beneficial than even distribution of load across parts.
So, rather than splitting hairs over an even distribution ofload across parts, we can achieve this by creating far more parts thanthe number of threads. Set the number of parts large enough so there’s enough work for all the available cores to perform on the program.
For those IO-Insive applications:
Having more threads than the number of cores does not help—we see that for each partitioning, the curve flattens past the pool size of eight.
-
Having more partitions is better than having fewer, because more partitions help keep the cores busy—this is quite evident from the curves.
-
After a certain number of large partitions, having more partitions has little benefit. Worker threads are already fully loaded. More tasks just make the busy period last longer.
3)Isolated Mutability
总是尝试用 CompletionService 来收集结果, 类似foldLeft/foldRight
总结:
1) We can easily avoid race conditions or consistency issues once we fully eliminate shared mutable state. When threads don’t compete tto access mutable data, there’s no issue of visibility and crossing the memory barrier. We also don’t have to worry about controlling the execution sequence of threads; since they don’t compete, there are no mutually exclusive sections to safeguard in code.
Provide shared immutability where possible. Otherwise, follow isolated mutability—ensure only one thread ever can access that mutable variable. We’re not talking about synchronizing shared state here. We’re ensuring that only one thread ever has access to that mutable variable, period.
2) How many threads we create and how we partition the problem affects the performance of your concurrent application.
First, in order to benefit from concurrency, we must be able to partition problems into smaller tasks that can be run concurrently. If a problem has a significant part that can’t be partitioned, then the application may not really see much performance gain by making it concurrent.
-
If tasks are IO intensive or have significant IO operations, then having more threads will help. In this case, the number of threads should be much greater than the number of cores. We can estimate the number of threads using the formula presented in Determining the Number of Threads, on page 16.
-
For a computationally intensive process, having more threads than cores may actually hurt—see Concurrent Computation of Prime Numbers. However, we’ll benefit by having at least as many threads as the number of cores, assuming the problem can be partitioned into at least as many tasks as the number of threads.
-
The workload of each part and how much time each part takes to complete relative to others both affect performance. A uniform partitioning of the problem may take too much effort and may not yield better results than ad hoc partitioning. Weigh the efforts vs. the benefit. We should try to arrive at a fair workload by using a simple approach to partitioning. In any case, good partitioning requires understanding the nature of the problem and its
阅读(974) | 评论(0) | 转发(0) |