1. Лонгаддер
Он используется аналогично Atomiclong, но имеет лучшую производительность, чем Atomiclong.
Longadder и Atomiclong используют атомные операции для повышения производительности. Тем не менее, Longadder выполняет разделение горячей точки на основе Atomiclong. Разделение горячей точки аналогично уменьшению размера частиц блокировки в блокированной операции, разделяя блокировку на несколько замков для повышения производительности. В беззаконе, аналогичные методы могут быть использованы для повышения уровня успеха CAS, тем самым повышая производительность.
Longadder схема:
Метод реализации Atomiclong заключается в том, что внутри существует переменная значения. Когда несколько потоков самостоятельно увеличиваются и самообекуется, все они работают с уровня инструкции машины с помощью инструкций CAS, чтобы обеспечить атомичность параллелизма. Единственная причина, которая ограничивает эффективность Atomiclong, - это высокая параллельность. Высокая параллелизм означает, что чем CAS имеет более высокую вероятность отказа, больше времени повторения и чем больше нитей повторяет, тем выше вероятность отказа CAS, что становится порочным циклом, и эффективность атомалонга снижается.
Longadder разделит значение на несколько ячеек и складывает все ячейки до значения. Поэтому, добавляя и вычитая Longadder, вам нужно работать только на разных ячейках. Различные потоки выполняют операции CAS на разных ячеек. Конечно, скорость успеха CAS высока (представьте себе 3+2+1 = 6, один нить 3+1, другая потока 2+1, и, наконец, 8, Longadder не имеет API для умножения и деления).
Однако, когда число параллелизма не очень высокое, разделение на несколько ячеек также требует поддержания ячейки и суммирования, что не так эффективно, как реализация Atomiclong. Лонгаддер использовал умный способ решить эту проблему.
В первоначальной ситуации Longadder и Atomiclong одинаковы. Только когда CAS выходит из строя, значение будет разделено на ячейки. Каждый раз, когда сбой совершается, количество ячеек будет увеличено. Это также эффективно при низкой параллелизме. При высокой параллелистике этот «адаптивный» метод обработки не пройдет после достижения определенного количества ячеек, и эффективность будет значительно повышена.
Longadder - это стратегия обмена пространством на время.
2. Полная планка
Реализуйте интерфейс завершения (более 40 методов), большинство из которых используются в функциональном программировании. И поддержка потоковых вызовов
CompleteFuture - это улучшенная версия будущего в Java 8
Простая реализация:
Импорт java.util.concurrent.completablefuture; открытый класс AskThread реализует Runnable {overseableFuture <Integer> re = null; public askThread (overseableFuture <Integer> re) {this.re = re; } @Override public void run () {int myre = 0; try {myre = re.get () * re.get (); } catch (Exception e) {} System.out.println (myre); } public static void main (string [] args) бросает прерывание {final overseableFuture <Integer> future = new overseableFuture <Integer> (); новая ветка (новый AskThread (Future)). start (); // моделировать долгосрочный процесс расчета. Sleep (1000); // информировать результат завершения Future.complete (60); }} Самое раскритикованное в будущем - это то, что вы должны ждать и проверить, была ли задача выполнена самостоятельно. В будущем время выполнения задачи неконтролируемо. Самое большое улучшение полного размера заключается в том, что время для выполнения задачи также открыто.
Future.complete (60);
Используется для установки времени завершения.
Асинхронное выполнение полной пластины:
Public Static Integer Calc (Integer Para) {try {// Симуляция длительного потока выполнения. Sleep (1000); } catch (прерывание Exception e) {} вернуть para * para; } public static void main (string [] args) бросает прерывание, выполняющее, выполнение ExectionExcept {final overseableFuture <Integer> future = overseableFuture .supplyAsync (() -> calc (50)); System.out.println (future.get ()); } Streaming Call of overseableFuture: Public Static Integer Calc (Integer Para) {try {// Моделировать длинный поток выполнения. Sleep (1000); } catch (прерывание Exception e) {} вернуть para * para; } public static void main (string [] args) бросает прерывания, выполняющие, выполнение ExcutionExcept {overseableFuture <void> fu = oppentfuture .suplyAsync (() -> calc (50)) .ThenApply ((i) -> integer.toString (i). .thenaccept (System.out :: println); fu.get (); }Объедините несколько завершаемых функций:
Общественное статическое целочисленное число (целочисленное парара) {вернуть пара / 2; } public static void main (string [] args) бросает прерывания, прерывание, выполнение, excutionExcept {overseableFuture <void> fu = oppentfuture .supplyAsync (() -> calc (50)) .thencompose ((i) -> oppliblefuture.supplyasync (() -> Calc (i))) "/" ") .thenaccept (System.out :: println); fu.get (); } Эти примеры больше сосредоточены на некоторых новых функциях Java 8. Вот несколько примеров, чтобы проиллюстрировать эти функции, поэтому я не буду вдаваться в это глубину.
CompleteFuture имеет мало общего с производительностью, но важнее для поддержки функционального программирования и улучшения функций. Конечно, настройка времени завершения является основным моментом.
3. Stampedlock
В предыдущей статье было только что упомянуто разделение блокировки, и важной реализацией разделения блокировки является readwritelock. Stampedlock - это улучшение ReadWritelock. Разница между Stampedlock и ReadWriteLock состоит в том, что Stampedlock считает, что чтение не должно блокировать записи, и Stampedlock считает, что при чтении и письме взаимоисключающие, чтение следует перечитывать, а не позволяет писать ветку. Этот дизайн решает проблему написания голода темы, когда читает больше и меньше.
Таким образом, Stampedlock - это улучшение, которое имеет тенденцию писать потоки.
Пример Stampedlock:
Импорт java.util.concurrent.locks.stampedlock; открытый класс точка {private Double x, y; Частный финальный Stampedlock SL = новый StampedLock (); void перемещение (Double DelTax, Double Deltay) {// исключительно заблокированный метод Long Stamp = sl.Writelock (); попробуйте {x += deltax; y += deltay; } наконец {sl.unlockwrite (Stamp); }} двойное расстояние от Romorigin () {// метод только для чтения Long Stamp = sl.tryoptimistructRead (); Double CurrentX = x, custry = y; if (! sl.validate (mamp)) {mamp = sl.readlock (); try {currentx = x; custry = y; } наконец {sl.unlockread (stamp); }} return math.sqrt (currentx * currentx + current * currenty); }}Приведенный выше код имитирует записную ветку и ветку для чтения. Странство проверяет, является ли он взаимоисключающим в соответствии с маркой. При написании штампа один раз, он увеличивает определенную ценность.
TreyoptimistriceRead ()
Это ситуация, когда чтение и письмо не являются взаимоисключающими, как упомянуто.
Каждый раз, когда вы читаете ветку, вы сначала вынесете суждение
if (! sl.validate (mamp))
В проверке он сначала проверит, есть ли написание записи потока, а затем определит, совпадает ли входное значение, что и текущая марка, то есть определить, будет ли поток чтения читать последние данные.
Если есть написание ветка, или значение марки отличается, возврат не удается.
Если решение не удается, конечно, вы можете попытаться прочитать его неоднократно. В примере кода не разрешается пытаться читать его неоднократно, а вместо этого использует блокировку оптимизма, чтобы быть вырожденным в обычные блокировки чтения, чтобы прочитать его. Эта ситуация является пессимистическим методом чтения.
Stamp = sl.readlock ();
Идея реализации Stampedlock:
CLH SPIN LOCK: Когда приложение блокировки не сработает, поток чтения не будет немедленно приостановлен. Очередь с ожиданием резьбы будет поддерживаться в замке. Все потоки, которые применяются для блокировки, но в этой очереди не записываются успешные потоки. Каждый узел (один узел представляет собой поток) сохраняет заблокированный бит, чтобы определить, выпустил ли текущий поток блокировку. Когда нить пытается приобрести блокировку, он получает хвостовой узел текущей очереди ожидания в качестве узела предшественника. И используйте коды, такие как следующие, чтобы определить, успешно ли преамериканский узел выпустил блокировку
while (pred.locked) {
}
Этот цикл должен ждать, пока предыдущий узел выпустит блокировку, так что текущий поток не будет приостановлен операционной системой, тем самым повышая производительность.
Конечно, не будет бесконечных вращений, и нить будет приостановлена после нескольких спинов.