Java concurrency (Specific instances)--a few examples

Source: Internet
Author: User

Step-by-step optimization of page rendering capabilities

This section simulates a simple page rendering function that draws an HTML page into the image cache for simplicity, assuming that the HTML file contains only the label text and the image and URL of the booking size.

1. Serial Page renderer

The simplest way to do this is to do a serial processing of the HTML document: first draw the text, then draw the image, serial processing:

public class Singlethreadrenderer {    void Renderpage (charsequence source) {        rendertext (source);        list<imagedata> ImageData = new arraylist<imagedata> ();        For (Imageinfo imageinfo:scanforimageinfo (source))            Imagedata.add (Imageinfo.downloadimage ());        for (ImageData data:imagedata)            renderimage (data);}    }

There is a problem with this implementation because most of the time the image download process is waiting for the I/O operation to complete, during which the CPU hardly does any work. Therefore, this type of execution does not take full advantage of the CPU, allowing users to wait too long before they can see the final page. By decomposing the problem into multiple independent tasks and executing concurrently, you can live with higher CPU utilization and response sensitivity.

2. Using the future to implement the page renderer

In order for the page renderer to achieve higher concurrency, the rendering process is first decomposed into two tasks, one rendering all the text, and the other downloading all the images (one CPU-intensive, one is I/o-intensive). Callable and future help to represent the interaction of this collaborative task, the following code first creates a callable to download all the images, and when the main task needs an image, it waits for the result of the future.get call. If you're lucky, the image may have already been downloaded, even if not, at least to start downloading in advance.

public class Futurerenderer {private final Executorservice executor = Executors.newcachedthreadpool ();        void Renderpage (Charsequence source) {final list<imageinfo> Imageinfos = scanforimageinfo (source);                    callable<list<imagedata>> task = new callable<list<imagedata>> () { Public list<imagedata> Call () {list<imagedata> result = new arraylist<imagedata&                        gt; ();                        for (Imageinfo Imageinfo:imageinfos) Result.add (Imageinfo.downloadimage ());                    return result;        }                };        future<list<imagedata>> future = Executor.submit (Task);        RenderText (source);            try {list<imagedata> ImageData = Future.get ();        for (ImageData data:imagedata) renderimage (data); } catch (Interruptedexception e) {thread.cuRrentthread (). interrupt ();        Future.cancel (TRUE);        } catch (Executionexception e) {throw launderthrowable (E.getcause ()); }    }}

Of course, we can also optimize, the user does not need to wait for all the images to be downloaded, we can display the image immediately after each download.

3. Using Completionservice to implement page renderer

To achieve the completion of the download is immediately drawn, we need to know the picture download completed, for this scenario, Completionservice very well in line with the needs. Completionservice will produce a service that separates the new asynchronous task from the result of using the completed task. The producer submit the tasks performed by the user taking the completed tasks and processing their results in the order in which they were completed. The following code uses Completionservice to overwrite the implementation of the page renderer:

Public abstract class Renderer {private final executorservice executor;    Renderer (Executorservice executor) {this.executor = executor;        } void Renderpage (Charsequence source) {Final list<imageinfo> info = scanforimageinfo (source); completionservice<imagedata> completionservice = new Executorcompletionservice<imagedata> (EXECU        TOR);                For (final imageinfo Imageinfo:info) completionservice.submit (new callable<imagedata> () {                Public ImageData Call () {return imageinfo.downloadimage ();        }            });        RenderText (source); try {for (int t = 0, n = info.size (); t < n; t++) {future<imagedata> F = completionse                Rvice.take ();                ImageData ImageData = F.get ();            RenderImage (ImageData);   }} catch (Interruptedexception e) {thread.currentthread (). interrupt ();     } catch (Executionexception e) {throw launderthrowable (E.getcause ()); }    }}

Set a time limit for a task

Sometimes, if a task cannot be completed within a specified time, its results are no longer needed, and the task can be discarded at this time. For example, a Web application obtains ad information from an external ad server, but if the application does not respond within two seconds, a default ad page is displayed so that if the ad message does not live, the response performance of the site is not reduced, The Future.get method can be implemented:

    Page Renderpagewithad () throws Interruptedexception {        long Endnanos = system.nanotime () + time_budget;        future<ad> f = exec.submit (new Fetchadtask ());        Render the page while waiting for the ad        page page = Renderpagebody ();        Ad ad;        try {            //Only wait for the remaining time budget            long timeLeft = Endnanos-system.nanotime ();            AD = F.get (TimeLeft, nanoseconds);        } catch (Executionexception e) {            ad = Default_ad;        } catch (TimeoutException e) {            ad = Default_ad;            F.cancel (True);        }        Page.setad (AD);        return page;    }

This "booking time" method can easily be extended to any number of tasks, consider a travel site: Users enter travel dates and requirements, the site through a variety of ways to obtain results, at this time, should not let the page response time is limited to the slowest way, but should only show the message received within the specified time, We can implement this requirement by submitting multiple tasks to a executorservice by using invokeall that support time-limited:

public class Timebudget {private static Executorservice exec = Executors.newcachedthreadpool ();                                                   Public list<travelquote> getrankedtravelquotes (Travelinfo travelinfo, set<travelcompany> companies,  Comparator<travelquote> ranking, long time, Timeunit unit) throws        interruptedexception {list<quotetask> tasks = new arraylist<quotetask> ();        for (Travelcompany company:companies) Tasks.add (New Quotetask (company, Travelinfo));        List<future<travelquote>> futures = Exec.invokeall (tasks, time, unit);        List<travelquote> quotes = new Arraylist<travelquote> (Tasks.size ());        iterator<quotetask> taskiter = Tasks.iterator ();            for (future<travelquote> f:futures) {quotetask task = Taskiter.next ();            try {quotes.add (F.get ());    } catch (Executionexception e) {            Quotes.add (Task.getfailurequote (E.getcause ()));            } catch (Cancellationexception e) {quotes.add (Task.gettimeoutquote (e));        }} collections.sort (quotes, ranking);    return quotes;    }}class Quotetask implements callable<travelquote> {private Final Travelcompany company;    Private final Travelinfo Travelinfo;        Public Quotetask (Travelcompany company, Travelinfo travelinfo) {this.company = Company;    This.travelinfo = Travelinfo;    } travelquote Getfailurequote (Throwable t) {return null;    } travelquote Gettimeoutquote (Cancellationexception e) {return null;    Public Travelquote Call () throws Exception {return company.solicitquote (travelinfo); }}interface Travelcompany {travelquote solicitquote (Travelinfo travelinfo) throws Exception;} Interface Travelquote {}interface Travelinfo {}

Examples from: "Java Concurrency Programming Combat"

  

Java concurrency (Specific instances)--a few examples

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.