Java concurrency and multithreading 2: 3 ways to achieve array summation
This article demonstrates three examples of array summation.
Example 1: single thread
Example 2: multithreading, synchronous summation (blocking if the calculation is not completed)
Example 3: multi-thread, asynchronous summation (accumulate the completed computing results first)
Example 1-code
Package cn.fansunion.exe cutorservice; public class BasicCaculator {public static long sum (int [] numbers) {long sum = 0; for (int I = 0; I
Example 2-code ExecutoreService provides the submit () method, passing a Callable or Runnable, and returning Future. If the Executor background thread pool has not completed Callable calculation, this call returns the get () method of the Future object, blocking until the calculation is complete.
Package cn.fansunion.exe cutorservice; import java. util. arrayList; import java. util. list; import java. util. concurrent. callable; import java. util. concurrent. executionException; import java. util. concurrent. executorService; import java. util. concurrent. executors; import java. util. concurrent. future; import java. util. concurrent. futureTask; // sum of the arrays for concurrent computing, "Synchronize" and public class ConcurrentCalculator {private ExecutorService exec; // This place is purely "wishful thinking ", "Parallel Execution" is not controlled by us, depending on the "attitude" of the Operating System private int cpuCoreNumber; private List
> Tasks = new ArrayList
> (); Class SumCalculator implements Callable
{Private int [] numbers; private int start; private int end; public SumCalculator (final int [] numbers, int start, int end) {this. numbers = numbers; this. start = start; this. end = end;} public Long call () throws Exception {Long sum = 0L; for (int I = start; I <end; I ++) {sum + = numbers [I];} return sum ;}} public ConcurrentCalculator () {cpuCoreNumber = Runtime. getRuntime (). availableProcessors (); exec = Executors. newFixedThreadPool (cpuCoreNumber);} public Long sum (final int [] numbers) {// Splits a task based on the number of CPU cores, creates a FutureTask, and submits it to Executorfor (int I = 0; I <cpuCoreNumber; I ++) {int increment = numbers. length/cpuCoreNumber + 1; int start = increment * I; int end = increment * I + increment; if (end> numbers. length) end = numbers. length; SumCalculator subCalc = new SumCalculator (numbers, start, end); FutureTask
Task = new FutureTask
(SubCalc); tasks. add (task); if (! Exec. isShutdown () {exec. submit (task) ;}} return getResult () ;}/ *** iterates each task, obtains the part, and returns */public Long getResult () {Long result = 0l after addition; for (Future
Task: tasks) {try {// if the calculation is not completed, blocking Long subSum = task. get (); result + = subSum;} catch (InterruptedException e) {e. printStackTrace ();} catch (ExecutionException e) {e. printStackTrace () ;}} return result;} public void close () {exec. shutdown ();}}
Example 3-code
In the preceding example, the FutureTask array is iterated during the implementation of the getResult () method. If the task is not completed, the current thread will be blocked.
If we want to add the result of any word task to the result without waiting for each task to complete in sequence, we can make the CompletionService.
The task executed by the producer submit. The user takes () completed tasks and processes their results in the order they are completed. That is, the take method that calls CompletionService is to return the result of putting the task back in the completed order.
The CompletionService maintains a blocking queue BlockingQueue. If no task is completed, the take () method is blocked.
Modify Example 2 and use CompletionService:
Package cn.fansunion.exe cutorservice; import java. util. concurrent. callable; import java. util. concurrent. completionService; import java. util. concurrent. executionException; import java. util. concurrent. executorCompletionService; import java. util. concurrent. executorService; import java. util. concurrent. executors; // sum of arrays for concurrent computing, "Asynchronous" sum of public class ConcurrentCalculatorAsync {private ExecutorService exec; private CompletionService
CompletionService; // This place is purely "wishful thinking". "Parallel Execution" is not under our control, depending on the "attitude" of the Operating System private int cpuCoreNumber; class SumCalculator implements Callable
{Private int [] numbers; private int start; private int end; public SumCalculator (final int [] numbers, int start, int end) {this. numbers = numbers; this. start = start; this. end = end;} public Long call () throws Exception {Long sum = 0l; for (int I = start; I <end; I ++) {sum + = numbers [I];} return sum ;}} public ConcurrentCalculatorAsync () {cpuCoreNumber = Runtime. getRuntime (). availableProcessors (); exec = Executors. newFixedThreadPool (cpuCoreNumber); completionService = new ExecutorCompletionService
(Exec);} public Long sum (final int [] numbers) {// split the task based on the number of CPU cores, create a FutureTask, and submit it to Executorfor (int I = 0; I <cpuCoreNumber; I ++) {int increment = numbers. length/cpuCoreNumber + 1; int start = increment * I; int end = increment * I + increment; if (end> numbers. length) {end = numbers. length;} SumCalculator subCalc = new SumCalculator (numbers, start, end); if (! Exec. isShutdown () {completionService. submit (subCalc) ;}} return getResult () ;}/ *** iterates each task to obtain the part and return the sum */public Long getResult () {Long result = 0l; for (int I = 0; I <cpuCoreNumber; I ++) {try {Long subSum = completionService. take (). get (); result + = subSum; System. out. println ("subSum =" + subSum + ", result =" + result);} catch (InterruptedException e) {e. printStackTrace ();} catch (ExecutionException e) {e. printStackTrace () ;}} return result;} public void close () {exec. shutdown ();}}
Run code
Package cn.fansunion.exe cutorservice; import java. math. bigDecimal; // The sum of the array is three Demopublic class ArraySumDemo {public static void main (String [] args) {int n = 200000000; int [] numbers = new int [n]; for (int I = 1; I <= n; I ++) {numbers [I-1] = I;} basic (numbers); long time = System. currentTimeMillis (); concurrentCaculatorAsync (numbers); long endTime = System. currentTimeMillis (); System. out. println ("multi-core parallel computing, asynchronous addition:" + time (time, endTime); long time2 = System. currentTimeMillis (); concurrentCaculator (numbers); long endTime2 = System. currentTimeMillis (); System. out. println ("multi-core parallel computing, synchronization addition:" + time (time2, endTime2);} private static void basic (int [] numbers) {long time1 = System. currentTimeMillis (); long sum = BasicCaculator. sum (numbers); long endTime1 = System. currentTimeMillis (); System. out. println ("single thread:" + time (time1, endTime1); System. out. println ("Sum:" + sum);} private static double time (long time, long endTime) {long costTime = endTime-time; BigDecimal bd = new BigDecimal (costTime ); // originally thought about converting millisecond to second, and finally found that the calculation is too fast BigDecimal unit = new BigDecimal (1L); BigDecimal s = bd. divide (unit, 3); return s. doubleValue () ;}// parallel computing, "synchronization" and private static void concurrentCaculator (int [] numbers) {ConcurrentCalculator calc = new ConcurrentCalculator (); Long sum = calc. sum (numbers); System. out. println (sum); calc. close () ;}// parallel computing, "Asynchronous" sum private static void concurrentCaculatorAsync (int [] numbers) {ConcurrentCalculatorAsync calc = new ConcurrentCalculatorAsync (); Long sum = calc. sum (numbers); System. out. println ("Sum:" + sum); calc. close ();}}
Console output
Single thread: 93.0
Sum: 20000000100000000
SubSum = 3750000175000002, result = 3750000175000002
SubSum = 1250000075000001, result = 5000000250000003
SubSum = 6250000275000003, result = 11250000525000006
SubSum = 8749999574999994, result = 20000000100000000
Sum: 20000000100000000
Multi-core parallel computing, asynchronous addition: 786.0
20000000100000000
Multi-core parallel computing, synchronization addition: 650.0
My opinion: the time of the three code segments is for reference only, and no interference factors are excluded.
In general, the execution speed of a single thread is faster, because the "array summation" itself does not require additional resources and does not block it.
Multithreading increases the time overhead of "Thread Scheduling.
We can also see that CPU computing is still very fast. "200000000" 0.2 billion integers are added in less than 0.1 seconds.
Episode
At first, I misunderstood the code. Think that "splitting tasks based on the number of CPU cores", at this time, "multithreading" is "Parallel.
In fact, not necessarily, not only the number of CPU cores, but also the distribution of the operating system.
// Split tasks based on the number of CPU cores, create FutureTask, and submit it to Executor
For (int I = 0; I <cpuCoreNumber; I ++ ){
}
At the very beginning, I was still thinking about "single thread", "multi-core parallel + multi-thread concurrency", and "Single-core + multi-thread concurrency" to achieve "array summation" in several situations ".
Finally, I felt like I was thinking too much. "Parallelism" should not be controlled by itself. It can only be controlled by "single thread" or "multi-thread ".
In the "java concurrent programming-Executor framework" article, "Example: Sum of arrays in parallel computing ." This is misleading and cannot be guaranteed to be "Parallel Computing ".
Tip: articles on the Internet are for reference only and need your own judgment.
With regard to Java-multi-core-parallel-multithreading, I initially thought that "multithreading can be executed in parallel, but it is not controlled by ourselves, depending on the operating system ".
Some Opinions of netizens:
Opinion 1:
Can java threads run on multiple cpu cores?
I always thought that the answer to this question is yes, that is, it can run on multiple cores.
But one day I saw such a theory, and I suddenly ruined the three views.
JVM acts as a process in the operating system. All java threads run from this JVM process,
Therefore, java threads can only run on one core at a time.
This statement is a big blow to me and I cannot accept it. So we started to verify the situation from multiple parties. Online Search and discussion with friends,
It was finally confirmed that java threads can run on multiple cores. Why?
The following sentence will wake you up:
All modern operating systems use threads as the minimum scheduling unit and processes as the minimum unit for resource allocation. In windows, the process is not active,
It is only used as a thread container.
That is to say, all threads in java are indeed in the JVM process, but the CPU schedules the threads in the process.
Opinion 2:
Can multithreading in JAVA be executed in parallel on multiple CPU machines? Note: I am not talking about concurrent execution.
We use java to write a multi-threaded program and start a JVM process. Therefore, these threads are all in this JVM process. I don't know the same time, can multiple CPUs run the same process and then execute different threads in the same process in parallel? Always confused
Your idea is right. the CPU is designed to cater to the multi-thread operating system and thus improve the computing efficiency of the system. however, it is not JAVA or JVM but the operating system to execute specific tasks in each kernel.
That is to say, The multithreading you run may be allocated to the same CPU kernel for running. or it may not run in different CPUs. if you can control the CPU allocation, it should be implemented by the operating system api.
I used JAVA to create a thread. At this time, both the main thread and the Child thread are running. Which means that the dual-core CPU may run these two threads concurrently at the same time point?
I have read a lot of JAVA chapters on multithreading, and I have not said that multi-core CPU runs JAVA multithreading. It seems that all of them have been single-core as an example, so I always think it may be concurrent, not parallel?
No, you need to separate your software thread from the CPU processing thread of the computer. Simply put, you cannot control the CPU allocation of tasks.
More code examples:
Http://git.oschina.net/fansunion/Concurrent (coming soon)
References:
Java concurrent programming-Executor framework
Http://www.iteye.com/topic/366591
Can java threads run on multiple cpu cores?
Http://blog.csdn.net/maosijunzi/article/details/42527553
Can multithreading in JAVA be executed concurrently on multiple CPUs? Note: I am not talking about concurrent execution.
Http://zhidao.baidu.com/link? Url = e11sEOSNFoLTfVyP-5FfpktIXEgbMQkbLAzvgh8mn4V16n_qQas89voj5gVhOEkho0jRA7fp_vbnElxKgeQCDrOxGkcu6xAWaUniqpcWg33