В проекте часто есть некоторые задачи, которые необходимо выполнять асинхронно (представленные в пул потоков) для выполнения, в то время как основной поток часто должен знать результаты асинхронного выполнения. Что мы должны делать в это время? Это невозможно достичь с помощью запуска, нам нужно использовать Callable, чтобы прочитать следующий код:
Импорт java.util.concurrent.callable; import java.util.concurrent.executionexception; import java.util.concurrent.executorservice; import java.util.concurrent.executors; import java.util.concurrent.future; public class addtask ulplesable <intreheg.util.concurrent.future; public class addtak allable <intreheg.util.concurrent.future; public class. public addTask (int a, int b) {this.a = a; this.b = b; } @Override public integer call выбрасывает исключение {integer result = a + b; результат возврата; } public static void main (string [] args) бросает прерывания, выполняющий, executionException {experationservice executor = executors.newsingleThreadExeCutor; // JDK вернулся до сих пор и является экземплярами FutureTask Future <Integer> Future = Executor.submit (New AddTask (1, 2)); Integer result = future.get; // Только после завершения статуса будущего (Future.isdone = true), метод получения вернет}} Хотя мы можем реализовать требование получения асинхронных результатов выполнения, мы обнаружили, что это будущее на самом деле не полезно, поскольку оно не обеспечивает механизм уведомлений, что означает, что мы не знаем, когда будущее будет завершено (если нам нужно опросить Isdone (), чтобы судить, кажется, что нет необходимости использовать это). Взгляните на интерфейс метод java.util.concurrent.future.future:
Public Interface Future <v> {Boolean Cancel (Boolean MayIntertifrunning); логический Iscancelled; логический isdone; V Получите броски прерванного эктриэктивы, выполнение Exception; V Get (Long Timeout, TimeUnit Unit) Throws TreamptedException, executionException, TimeOutException;} Из этого мы видим, что будущий механизм JDK на самом деле не прост в использовании. Если вы можете добавить слушателя в это будущее и позволить ему уведомить слушателя после его завершения, он будет проще использовать, как и следующая ifuture:
пакет будущего; импорт java.util.concurrent.cancellationexception; import java.util.concurrent.future; import java.util.concurrent.timeUnit;/*** Результат асинхронной операции. * * @author lixiaohui * @param <v> type Параметр результата выполнения */public inface ifuture <v> расширяет будущее <v> {boolean issuccess; // успешно ли V getNow; // немедленно вернуть результат (независимо от того, находится ли будущее в завершенном состоянии) бросаемой причиной; // Причина неудачи выполнения отменяется; // Могу ли я отменить ifuture <v> await, бросает прерывания, прерывания; // ждем будущего завершения логическое ожидание (давняя Timeoutmillis) бросает прерванную экспрессию; // Тайм -аут ожидание для будущего завершения логическое ожидание (давний тайм -аут, TimeUnit TimeUnit) бросает прерывания; Ifuture <v> AwaitUnintertaill; // ожидание будущего завершения, без прерывания логии, непрерывно прерываемо (давняя Timeoutmillis); // Тайм -аут ожидает будущего завершения, без прерывания. Ifuture <v> addlistener (ifutureListener <v> l); // Когда будущее будет завершено, эти добавленные слушатели будут уведомлены ifuture <v> RemoveListener (ifutureListener <v> l); } Далее, давайте реализуем это ifuture вместе. До этого мы объясним объект. Ввидай, объект. Взгляните на объяснение в JDK:
Общественный объект класса { /** * заставляет текущий поток ждать, пока другой поток не вызовет метод * {@link java.lang.object#notify} или метод * {@link java.lang.object#notifyall} для этого объекта. * Другими словами, этот метод ведет себя точно так же, как если бы он просто * выполняет вызов {@Code WAIT (0)}. * После вызова этого метода текущий поток выпустит блокировку монитора объекта и отказался от права на использование ЦП. Пока другой поток вызовет уведомление/ уведомление */ public final void waud, прерывания, {wate (0); } /*** Разбудит все потоки, которые ждут на мониторе этого объекта. Поток * ждет на мониторе объекта, вызывая один из методов * {@code WAIT}. * <p> * Пробужденные потоки не смогут продолжить до тех пор, пока текущий * поток не откажется от блокировки этого объекта. Пробужденные потоки * будут конкурировать обычным образом с любыми другими потоками, которые могут * активно конкурировать, чтобы синхронизировать этот объект; Например, * Пробужденные потоки не пользуются достоверной привилегией или недостатком в *, будучи следующим потоком, чтобы заблокировать этот объект. */ public final native void notifyall;} Узнав это, у нас есть идея, чтобы самостоятельно реализовать будущее. Когда поток вызывает серию методов, таких как ifuture.await, если будущее не будет завершено, то вызовите метод будущего. Ввидеть, чтобы поток вошел в состояние ожидания. Когда другие потоки устанавливают будущее в состояние завершения (обратите внимание, что состояние завершения здесь включает в себя нормальный конец и ненормальный конец), необходимо вызвать метод будущего. Полная реализация заключается в следующем (код не должен быть трудно понять. Я ссылаюсь на будущий механизм Нетти. Если вы заинтересованы, вы можете проверить исходный код Нетти):
Пакет будущего; импорт java.util.collection; import java.util.concurrent.cancellationexception; import java.util.concurrent.copyonwritearraylist; import java.util.concurrent.executionexception; import java.util.concurrent.timeUnit; импорт java. <pre> * На нормальном конце, если результат выполнения не является нулевым, то результатом является результат выполнения; Если результат выполнения является нулевым, то Result = {@link AbstractFuture#Success_signal} * Когда исключение заканчивается, результат является экземпляром {@link causeholder}; Если исключение заканчивается из -за отмены, результатом является экземпляр {@link CancellationException}, в противном случае это экземпляр других исключений * Следующие ситуации приведут к передаче асинхронной операции из незаконченного состояния в завершенное состояние, то есть метод уведомления, когда возникает метод; <li> Когда асинхронная операция заканчивается нормально (метод setSuccess) </li> * <li> Когда асинхронная операция заканчивается ненормально (метод setFailure) </li> * </ul> * </pre> * @author lixiaohui * * @param <v> * Тип Asynchronous execution rececative */public class -reblemtfure <v> v> v> v> v> v> protecture <v> v> protecture uit <v> Результат нестабильного объекта; // это должно быть гарантированно быть видимостью/ *** Слушатель SET*/ Защищенная коллекция <ifutureListener <v >> Слушатели = новый CopeonWritearRaylist <ifutureListener <v >>; / *** Когда нормальный результат выполнения задачи является нулевым, то есть, когда клиент вызывает {@link AbstractFuture#setSuccess (null)},* Результат ссылается на объект*/ private static final uscignal uscys_signal = new SuccessIgnal; @Override public boolean cancel (boolean mayintruptifrunning) {if (isdone) {// return false не может быть отменено; } synchronized (this) {if (isdone) {// Двойная проверка вернуть false; } result = new Causeholder (New CancellationException); уведомлять; // isdone = true, уведомить поток, ожидающий ожидания на объекте} notifylisteners; // Уведомление слушателя о том, что асинхронная операция была завершена, вернуть истину; } @Override public boolean iscancellable {return result == null; } @Override public boolean iscancelled {return result! = Null && result ancessionof caseholder && ((Causholder) Результат). } @Override public boolean isdone {return result! = Null; } @Override public v получение бросков прерывания, выполнения, executionException {wait; // ждать результата выполнения, причина, причина = причина; if (причина == null) {// Исключение не было, асинхронная операция заканчивалась обычно возвращать getNow; } if (причина exanceOf DecallationException) {// Асинхронная операция была отменена throd (decellationException) canie; } бросить новое выполнение ExectionException (canes); // другие исключения} @Override public v get (Long Timeout, TimeUnit Unit) Throws ErruptEdException, executionException, TimeOutException {if (wawait (timeout, unit)) {// ждать тайм -аута для получения результата выполнения. if (причина == null) {// Исключение не было, асинхронная операция заканчивалась обычно возвращать getNow; } if (причина exanceOf DecellationException) {// Асинхронная операция была отменена броска (DecallationException) Cause; } бросить новое executionException (canes); // другие исключения} // Время еще не закончилось, бросая тайм -аут, бросает новый TimeOutException; } @Override public boolean issuccess {return result == null? false:! (результат экземпляра причина); } @Suppresswarnings ("unchecked") @Override public v getNow {return (v) (result == uccess_signal? Null: result); } @Override public throwable cause {if (result! = Null && result exactionof caseholder) {return (((Causholder) result) .cause; } return null; } @Override public ifuture <v> addlistener (ifutureListener <v> слушатель) {if (слушатель == null) {бросить новое NullPointerException ("Слушатель"); } if (isdone) {// Если вы завершили notifylistener (слушатель); вернуть это; } synchronized (this) {if (! Isdone) {слушатели.add (слушатель); вернуть это; }} notifylistener (слушатель); вернуть это; } @Override public ifuture <v> removeListener (ifutureListener <v> слушатель) {if (слушатель == null) {бросить новое NullPointerException ("Слушатель"); } if (! ISDONE) {Слушатели.REMOVE (Слушатель); } вернуть это; } @Override public ifuture <v> await throws прерывает ErruptEdException {return await0 (true); } private ifuture <v> await0 (boolean retruptable) броски прерывания {if (! isdone) {// Если оно было завершено, он будет возвращен непосредственно // Если терминал разрешен и прерывается, исключение прерывания будет выброшено, если (прерываемое && tread.traintrupted) {throut newruptuptedException (threadtry -retruprent.TrathrayT.TrakRement.Reatrent. прерван. "); } boolean прерван = false; синхронизированный (это) {while (! Isdone) {try {ждать; // Отпустите блокировку и введите состояние ожидания, подождите, пока другие потоки вызовывают метод уведомления объекта/уведомление} catch (прерывание Exception e) {if (retretable) {throw e; } else {прерван = true; }}}}} if (прерван) {// Почему нам нужно установить здесь флаг прерывания? Потому что после возвращения из метода ожидания флаг прерывания очищается, // сбросить здесь, чтобы другие коды знали, что он прерывается здесь. Thread.currentThread.interrupt; }} вернуть это; } @Override public boolean wait (long timeoutmillis) бросает прерванные эктриэкцепции {return await0 (timeUnit.milliseconds.tonanos (timeoutmillis), true); } @Override public boolean wait (Long Timeout, TimeUnit Unit) Throws TreamptEdException {return await0 (Unit.tonanos (Timeout), True); } private boolean await0 (длинный Timeoutnanos, логическое прерывание) бросает прерывания {if (isdone) {return true; } if (timeOutnanos <= 0) {return ISdone; } if (Interruptable && think.Erengtted) {бросить новый прерываний (toString); } long StartTime = TimeOutnanos <= 0? 0: System.nanotime; долгое ожидание = timeoutnanos; Boolean прерван = false; try {synchronized (this) {if (isdone) {return true; } if (waitTime <= 0) {return ISdone; } for (;;) {try {wate (waftime / 1000000, (int) (wailtime % 1000000)); } catch (прерывание Exception e) {if (прерывание) {throw e; } else {прерван = true; }} if (isdone) {return true; } else {waittime = timeOutnanos - (System.Nanotime - startTime); if (waftime <= 0) {return isdone; }}}} / }}} @Override public ifuture <v> awaitUnintertabulal {try {return await0 (false); } catch (прерывание Exception e) {// Если здесь брошено исключение, с ним нельзя обрабатывать. }} @Override public boolean waitUnintertabull (давняя Timeoutmillis) {try {return await0 (timeUnit.milliseconds.tonanos (timeoutmillis), false); } catch (прерванная экспрессия e) {бросить новый java.lang.internalerror; }} @Override public boolean waitUnintertabull (Long Timeout, TimeUnit Unit) {try {return await0 (unit.tonanos (timeout), false); } catch (прерванная экспрессия e) {бросить новый java.lang.internalerror; }} защищенный ifuture <v> setFailure (причина бросания) {if (setFailure0 (canele)) {notifylisteners; вернуть это; } бросить новое alloslestateException («oppl уже:» + это); } private boolean setfailure0 (throwable case) {if (isdone) {return false; } синхронизированный (this) {if (isdone) {return false; } result = новый причина (причина); уведомлять; } вернуть true; } защищенный ifuture <v> setSuccess (object result) {if (setSuccess0 (result)) {// notifyListeners после успешного настройки; вернуть это; } бросить новое alloslestateException («oppl уже:» + это); } private boolean setSuccess0 (object result) {if (isdone) {return false; } синхронизированный (this) {if (isdone) {return false; } if (result == null) {// Результат нормального выполнения асинхронной операции - null this.result = success_signal; } else {this.result = result; } notifyall; } вернуть true; } private void notifylisteners {for (ifutureListener <v> l: слушатели) {notifylistener (l); }} private void notifylistener (ifutureListener <v> l) {try {l.OperationCompleted (this); } catch (Exception e) {e.printstacktrace; }} частный статический класс успешности {} частного статического окончательного класса Causeholder {final Throwable Case; Причина (бросаемая причина) {this.cause = canele; }}} Так как это использовать? С помощью приведенной выше реализации скелета мы можем настроить различные асинхронные результаты. Ниже приводится задержка задачи:
пакет future.test; import future.ifuture; import future.ifutureListener;/** * Задержка сложения * @author lixiaohui * */public class delayaddder {public static void main (string [] args) {new DelayDadder.add (3 * 1000, 1, 2). AddDliesener (newfuTurelistener <intreger> OperationCompleted (ifuture <Integer> Future) Throws Exception {System.out.println (Future.getNow); } / *** Задержка добавления* @param продолжительность задержки задержки миллисекунды* @param Added* @param b Добавление* @return Asynchronous Result* / public DelayAdditionFuture Add (длинная задержка, int a, int b) {DelesAdditionFuture Future = new DeleStadditionFuture; Новая ветка (новый DelesAdditionTask (Delay, A, B, Future)). Start; вернуть будущее; } частного класса задержка Частный int a, b; частное задержка в будущем; Public DelesAdditionTask (длинная задержка, int a, int b, doweradditionfuture future) {super; this.delay = задержка; this.a = a; this.b = b; this.future = будущее; } @Override public void run {try {thread.sleep (dower); Целое число I = A + B; // todo Вот будущее, установленное на статус завершения (нормальное выполнение завершено) Future.setSuccess (i); } catch (прерывание Exception e) {// todo Вот будущее, установленное в статусе завершения (исключение завершено) future.setFailure (e.getCaue); }}}} упаковка Future.test; import future.abstractfuture; import future.ifuture; // просто выставить два метода для внешнего открытого открытого класса DelayAdditionFuture AbstractFuture <Integer> {@Override public ifuture <Integer> setSuccess (объект результат) {return Super.setSuccess (результат); } @Override public ifuture <Integer> setFailure (бросаемая причина) {return super.setFailure (Canies); }} Вы можете видеть, что клиенту не нужно активно спрашивать, будет ли будущее завершено, но автоматически вызовет метод OperationCompleted, когда будущее будет завершено. Клиент должен только реализовать логику в обратном вызове.
Выше всего содержание этой статьи. Я надеюсь, что это будет полезно для каждого обучения, и я надеюсь, что все будут поддерживать Wulin.com больше.