definition of a task
Most concurrent programs are managed around tasks. A task is an abstract and discrete unit of work.
execution strategy for a task
1. Sequential execution of tasks
This strategy is characterized by the generally only sequential processing of incoming tasks. Only one task can be processed at a time, and then other tasks are waiting to be processed. Poor responsiveness, low throughput. Low system resource utilization.
2. Create a thread for the task shown
One thread is created for each task, the response is fast, and the system resources take advantage of the path. The disadvantage is that the resource consumption is large, and if there are a large number of tasks to be executed, the system will run out of memory due to unlimited creation of excessive threads. Especially when the number of threads created is much larger than the CPU cores of the system, Because each core can only execute one thread at a time, the system performs a lot of unnecessary thread context switching, resulting in a lot of wasted resources.
3.Executor Frame
The executor interface itself is simple, just an execute method. But the classes derived from the executor interface are very powerful. So to think, executor framework this is a tool for threading management. You can manage the lifecycle of a thread and the execution policy.
Executor interface
Public Interface Executor { void execute (Runnable command);}
The executor framework is implemented by Threadpoolexecutor and is simply understood as a thread pool. In fact, threads are managed through a thread pool and a blocking queue blockingqueue<runnable>.
Page Renderer Instance
The example is to achieve 2 tasks, the first is to render the text (fast), the second is to render the picture (slow). When you render a picture, you need to download the image before you can render it.
1. First way: Sequential execution of page rendering
Public classSinglethreadrenderer { Public voidrenderpage (charsequence source) {RenderText (source);//working with text, fastList<ImageData> ImageData =NewArraylist<>(); for(Imageinfo info:scanforimageinfo (source)) {Imagedata.add (Info.downloadimage ());//download pictures, slow } for(ImageData data:imagedata) {renderimage (data);//working with pictures } }}
This implementation is simple, but the disadvantage is also obvious, that rendering text and rendering pictures can not be executed concurrently, low CPU utilization.
2. Second way: Using the future to implement the page renderer
The future can hold the execution result of an asynchronous concurrent thread, and executors can perform concurrent operations on the thread.
Public classFuturerenderer {Private FinalExecutorservice exec =Executors.newfixedthreadpool (Runtime. GetRuntime (). Availableprocessors ()); Public voidrenderpage (charsequence source) {FinalList<imageinfo> Imageinfos =scanforimageinfo (source); Callable<List<ImageData>> task =NewCallable<list<imagedata>>() { PublicList<imagedata> Call ()throwsException {List<ImageData> ImageData =NewArraylist<>(); for(Imageinfo Info:imageinfos) {Imagedata.add (Info.downloadimage ());//download pictures, slow } returnImageData; } }; Future<List<ImageData>> f =Exec.submit (Task); //the thread that renders the picture is executing while the text task is being processedRenderText (source);//working with text, fast Try{List<ImageData> Imagedatas =F.get (); for(ImageData data:imagedatas) {renderimage (data);//working with pictures } } Catch(Interruptedexception |executionexception e) { //TODO auto-generated Catch blockE.printstacktrace (); } }
}
This execution strategy still has limitations, because running heterogeneous tasks in parallel does not get good performance. Only a large number of independent and homogeneous tasks can be processed concurrently to achieve real performance gains.
3. Third Way: Using the Completionservice page renderer
Public classCompletionservicerenderer {Private FinalExecutorservice exec =Executors.newfixedthreadpool (Runtime. GetRuntime (). Availableprocessors ()); Public voidrenderpage (charsequence source) {FinalList<imageinfo> Imageinfos =scanforimageinfo (source); Completionservice<ImageData> Completionservice =NewExecutorcompletionservice<>(exec); for(Finalimageinfo Info:imageinfos) {Callable<ImageData> task =NewCallable<imagedata>() { PublicImageData Call ()throwsException {returnInfo.downloadimage (); } }; Completionservice.submit (Task); } rendertext (source);//working with text, fast for(inti = 0; I < imageinfos.size (); i++) { Try{ Future<ImageData> future =Completionservice.take (); ImageData ImageData=Future.get (); RenderImage (imageData);//working with pictures } Catch(Interruptedexception |executionexception e) { //TODO auto-generated Catch blockE.printstacktrace (); } } }}
?
This method does not have to wait to download all the pictures before processing, but each download a picture on the processing, achieved very good and released.
Java Concurrency Programming Practice (Reading Notes) task execution (not finished)