In a single -threaded application, when you call a method, the result will be returned only when the calculation is over.
Public String DownloadContents (URL URL) Throws IOEXCEPTION {Trystream Input = URL.OPENSTREAM ()) {Return IOUTILS.TRING (Input, Standardc Harsets.utf_8);}} // ... FINAL FUTURE <strong> Contents = DOWNLOADCONTENTS ( new url ("http://www.example.com");
DOWNLOADCONTENTS () looks harmless, but it needs to be done for a long time. At the same time, in order to reduce delay, during the waiting result, you may need to handle other work independently at the same time. In the past, you may start a new thread or wait for the results (sharing memory, lock, bad wait ()/notify () pair).
Through Future <t> mode, it will become clear:
Public Static Future <string> Startdownloading (URL URL) {// ...} Final Future <string> ContentsFuture = StartDownload (New, http://www.example .com ")); // Other ComputationFinal String Contents = ContentsFuture.get ();
We will realize startdownloading (), startdownloading () will not be blocked, but waiting for external sites to respond. It is important to understand this principle. On the contrary, if it returns quickly and returns a lightweight Future <string> object. This object is a promise, so the future string type is available. Although we don't know when it will be, it will keep this reference until it returns to the result and return, you can get it through Future.get (). In other words, Future is an agent or an object packaging, not a real target object. Once the asynchronous calculation is completed, you can extract it. So what kind of interface does Future provide?
Future.get () is the most important method. It blocks and wait until the result of the promise is available, so if we really need this string, call the get () method and wait. There is also a heavy load version that accepts timeout parameters. If there is a problem, you do n’t have to wait until you keep waiting for the set time.
In some cases, you may want to secretly look at whether Future is available. This can be done through Isdone (). Imagine a situation, your user is waiting for some asynchronous calculations. You want him to know this situation, and at the same time do some other calculations:
FINAL FUTURE <string> ContentsFuture = StartDownloading (new url ("http://www.example.com"); While (! ContentsFuture.isdone ()) {askusertowail (); do SomeComputationInThemeantime ();} ContentsFuture.get () ;;
Finally, the content of Future.get () is guaranteed to return immediately without being blocked, because Future.isdone () returns true. If you follow this model, you will not be busy waiting and calling Isdone () alternately every second.
Canceling Futrues is the last one we have not covered. Imagine that you start the asynchronous work and you can only wait for some time. If we give up after 2 seconds, we give up, or pass the error, or use a temporary solution to solve it. However, you are a good citizen, you should tell this Future object: I don't need you anymore, you don't care. Then you can save resources by stopping outdated tasks. The grammar is simple:
ContentsFuture.Cancel (true); // Meh ...
We all like to hide, Boer type parameters, right? The cancellation can be implemented through two ways: before the task starts, the FALSE parameter is canceled, provided that before the results of the Future expressed, the calculation starts. Once Callable.call () is running to half, then we want to let it end. If we pass through True, then future.call () will be invasive and try to interrupt the running work. Do you think this is good? Phenomena those who throw up InterruptedException, the infamous method, such as Thread.sleep (), Object.Wait (), Conition.await (), etc., even if you are blocked in this method And some people decide to cancel your call, they will undoubtedly throw the interruptionException, and send out someone to interrupt the task of current operation.
So we now understand what Future is --- a placeholder, you can get the target object in the future. Just like a car, there is no key to manufacture. But how can you get an instance of Future in the application? The two most common resources are thread pools and asynchronous methods (support of thread pool). Therefore, the Startdownloading () method can be rewritten as:
Private Final ExecutorService Pool = Executors.newfixedthreadPool (10); Public Future <string> StartDownloading (FINAL URL) Throws IOEXCEPTION { Return Pool.Submit (new call <string> () {@Override Public String Call () Throws Exception {Try (InputStream Input = URL.OPENSTREAM ()) {Return IOUTILS.TOSTRING (Input, StandardCharsets.utf_8);}});}
Although there are a lot of tedious grammar problems, the basic thinking is simple: packaging computing that needs to be running for a long time is packed to the adjustable <string>, and submit () to the thread pool. This thread pool contains 10 threads. After submitting, the implementation of Future <string> is like linking to your task and thread pool in some way. Obviously your task will not be executed immediately. On the contrary, it is placed in a queue and will be pulled out by the thread later. Now you need to figure out what the two special significance of Cancel () is to cancel the queue The task of staying in the middle can also cancel the task that has long been running, but this is a more complicated thing.
You can also meet Future in Spring and EJB. For example, you can add the annotation of @Async to the Spring framework:
@AsyncPublic Future <string> Startdownloading (Final URL URL) Throws IOEXception {Try (InputStream Input = URL.OPENSTREAM ()) {Return New Asyncres ult <> (iOutils.tostring (input, StandardCharsets.utf_8));}}}
Note that we simply implement Future through the packaging result to Asyncresult, but this method itself will not interact with the thread pool or processed asynchronous. Spring later will represent all calls to startdownloading () and execute in the thread pool. In EJB, the same feature is completed by adding @AsynChronousannotation.