JavaRush /Блоги Java /Random-TG /Шумо наметавонед Java-ро бо ришта вайрон кунед: Қисми IV ...
Viacheslav
Сатҳи

Шумо наметавонед Java-ро бо ришта вайрон кунед: Қисми IV - Callable, Оянда ва дӯстон

Дар гурӯҳ нашр шудааст

Муқаддима

Мо аллакай дида будем, ки чӣ гуна риштаҳо дар қисми аввал сохта мешаванд . Боз ба хотир меорем. Шумо наметавонед Java-ро бо ришта вайрон кунед: Қисми IV - Қобor даъват, Оянда ва дӯстон - 1Ришта Threadчизест, ки дар он кор мекунад run, аз ин рӯ биёед компилятори онлайни java tutorialspoint-ро истифода барем ва рамзи зеринро иҷро кунем:
public class HelloWorld {

    public static void main(String []args){
        Runnable task = () -> {
            System.out.println("Hello World");
        };
        new Thread(task).start();
    }
}
Оё ин ягона вариант барои иҷро кардани супориш дар ришта аст?

java.util.concurrent.Callable

Маълум мешавад, ки java.lang.Runnable бародар дорад ва номаш java.util.concurrent.Callable буда , дар Java 1.5 таваллуд шудааст. Фарқиятҳо чист? Агар мо ба JavaDoc-и ин интерфейс бодиққат нигоҳ кунем, мебинем, ки бар хилофи Runnableинтерфейси нав усулеро эълон мекунад call, ки натиҷа медиҳад. Инчунин, ба таври нобаёнӣ он истисноро мепартояд. Яъне, он моро аз зарурати навиштани try-catchблокҳо барои истисноҳои тафтишшуда наҷот медиҳад. Аллакай бад нест, дуруст? Ҳоло мо Runnableба ҷои вазифаи нав дорем:
Callable task = () -> {
	return "Hello, World!";
};
Аммо бо он чӣ бояд кард? Чаро ба мо ҳатто ба вазифае лозим аст, ки дар ришта иҷро карда мешавад, ки натиҷа медиҳад? Аён аст, ки дар оянда мо интизор мешавем, ки натиҷаи амалҳоеро, ки дар оянда иҷро мешаванд, ба даст орем. Оянда бо забони англисӣ - Оянда. Ва интерфейс бо ҳамон ном вуҷуд дорад:java.util.concurrent.Future

java.util.concurrent.Future

Интерфейси java.util.concurrent.Future API-ро барои кор бо вазифаҳое тавсиф мекунад, ки натиҷаҳои онҳоро мо дар оянда ба даст орем: усулҳои ба даст овардани натиҷаҳо, усулҳои санҷиши ҳолат. Мо Futureба татбиқи он манфиатдорем java.util.concurrent.FutureTask . Ин аст Taskон чизе ки дар он иҷро мешавад Future. Чизи ҷолиб дар бораи ин татбиқи он аст, ки он амалӣ мекунад ва Runnable. Шумо метавонед ин як навъ адаптери модели кӯҳнаи кор бо супоришҳо дар риштаҳо ва модели навро баррасӣ кунед (ба маънои нав, ки он дар java 1.5 пайдо шудааст). Инак як мисол:
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

public class HelloWorld {

    public static void main(String []args) throws Exception {
        Callable task = () -> {
            return "Hello, World!";
        };
        FutureTask<String> future = new FutureTask<>(task);
        new Thread(future).start();
        System.out.println(future.get());
    }
}
Тавре ки аз мисол дида мешавад, бо истифода аз усул мо getнатиҷаи масъаларо ба даст меорем task. (!) Муҳим, ки дар айни замон бо истифода аз усул натиҷа ба даст меояд, getиҷро синхронӣ мешавад. Ба фикри шумо кадом механизм дар ин ҷо истифода мешавад? Дуруст аст, блоки синхронизатсия вуҷуд надорад - бинобар ин мо ИНТИЗОРИ-ро дар JVisualVM на ҳамчун monitorё wait, балки ҳамчун ҳамон як мебинем park(зеро механизм истифода мешавад LockSupport).

Интерфейсҳои функсионалӣ

Минбаъд мо дар бораи синфҳо аз Java 1.8 сӯҳбат хоҳем кард, аз ин рӯ муқаддима кардани мухтасар муфид хоҳад буд. Биёед рамзи зеринро бубинем:
Supplier<String> supplier = new Supplier<String>() {
	@Override
	public String get() {
		return "String";
	}
};
Consumer<String> consumer = new Consumer<String>() {
	@Override
	public void accept(String s) {
		System.out.println(s);
	}
};
Function<String, Integer> converter = new Function<String, Integer>() {
	@Override
	public Integer apply(String s) {
		return Integer.valueOf(s);
	}
};
Рамзи нолозим зиёд аст, ҳамин тавр не? Ҳар як синфҳои эълоншуда як вазифаи ягонаро иҷро мекунанд, аммо барои тавсифи он мо як қатор codeҳои ёрирасони нолозимро истифода мебарем. Ва таҳиягарони Java низ чунин фикр мекарданд. Аз ин рӯ, онҳо маҷмӯи "интерфейсҳои функсионалӣ" ( @FunctionalInterface) -ро ҷорӣ карданд ва қарор доданд, ки ҳоло худи Java ҳама чизро барои мо "андеша" мекунад, ба истиснои интерфейсҳои муҳим:
Supplier<String> supplier = () -> "String";
Consumer<String> consumer = s -> System.out.println(s);
Function<String, Integer> converter = s -> Integer.valueOf(s);
Supplier- провайдер. Он параметр надорад, аммо чизеро бармегардонад, яъне онро таъмин мекунад. Consumer- истеъмолкунанда. Он чизеро ҳамчун вуруд (параметр s) мегирад ва бо он коре мекунад, яъне чизеро истеъмол мекунад. Функсияи дигар вуҷуд дорад. Он чизеро ҳамчун вуруд (параметр s) мегирад, коре мекунад ва чизеро бармегардонад. Тавре ки мебинем, генерикҳо фаъолона истифода мешаванд. Агар шумо боварӣ надошта бошед, шумо метавонед онҳоро ба ёд оред ва " Назарияи генерикҳо дар Java ё чӣ гуна гузоштани қавсҳоро дар амал " хонед.

Completable Future

Бо гузашти вақт, Java 1.8 синфи наверо бо номи CompletableFuture. Он интерфейсро амалӣ мекунад Future, яъне маънои мо taskдар оянда иҷро хоҳад шуд ва мо метавонем иҷро кунем getва натиҷа ба даст орем. Аммо ӯ баъзеро низ амалӣ мекунад CompletionStage. Аз тарчума максади он аллакай маълум аст: ин як мархилаи муайяни як навъ хисоб мебошад. Муқаддимаи мухтасари мавзӯъро дар шарҳи " Муқаддима ба CompletionStage ва CompletableFuture " пайдо кардан мумкин аст. Биёед рост ба матлаб гузарем. Биёед рӯйхати усулҳои мавҷудаи статикиро дида бароем, то ба мо дар оғоз ёрӣ расонанд: Шумо наметавонед Java-ро бо ришта вайрон кунед: Қисми IV - Зангшаванда, Оянда ва дӯстон - 2Дар ин ҷо имконоти истифодаи онҳо инҳоянд:
import java.util.concurrent.CompletableFuture;
public class App {
    public static void main(String []args) throws Exception {
        // CompletableFuture уже содержащий результат
        CompletableFuture<String> completed;
        completed = CompletableFuture.completedFuture("Просто meaning");
        // CompletableFuture, запускающий (run) новый поток с Runnable, поэтому он Void
        CompletableFuture<Void> voidCompletableFuture;
        voidCompletableFuture = CompletableFuture.runAsync(() -> {
            System.out.println("run " + Thread.currentThread().getName());
        });
        // CompletableFuture, запускающий новый поток, результат которого возьмём у Supplier
        CompletableFuture<String> supplier;
        supplier = CompletableFuture.supplyAsync(() -> {
            System.out.println("supply " + Thread.currentThread().getName());
            return "Значение";
        });
    }
}
Агар мо ин codeро иҷро кунем, мо мебинем, ки офариниш CompletableFutureоғоз кардани тамоми занҷирро дар бар мегирад. Аз ин рӯ, гарчанде ки бо SteamAPI аз Java8 каме шабоҳат вуҷуд дорад, ин фарқият байни ин равишҳост. Барои намуна:
List<String> array = Arrays.asList("one", "two");
Stream<String> stringStream = array.stream().map(value -> {
	System.out.println("Executed");
	return value.toUpperCase();
});
Ин як намунаи Java 8 Stream Api аст (шумо метавонед дар ин ҷо бештар дар бораи он хонед " Дастури Java 8 Stream API дар расмҳо ва мисолҳо "). Агар шумо ин codeро иҷро кунед, он Executedнамоиш дода намешавад. Яъне ҳангоми сохтани ҷараён дар Java ҷараён фавран оғоз намешавад, балки интизор мешавад, ки аз он арзиш лозим шавад. Аммо CompletableFutureон фавран занҷирро барои иҷро оғоз мекунад, бидуни интизори он ки арзиши ҳисобшуда аз он талаб карда шавад. Ман фикр мекунам, ки инро фаҳмидан муҳим аст. Ҳамин тавр, мо CompletableFuture дорем. Чӣ тавр мо метавонем занҷир эҷод кунем ва мо чӣ гуна воситаҳо дорем? Биёед дар бораи интерфейсҳои функсионалӣ, ки мо қаблан навишта будем, ба ёд орем.
  • Мо функсияе дорем ( Function), ки A-ро мегирад ва B-ро бармегардонад. Он як усули ягона дорад - apply(кор кардан).
  • Мо истеъмолкунанда дорем ( Consumer), ки A -ро қабул мекунад ва ҳеҷ чизро барнамегардонад ( Void ). Он танҳо як усул дорад - accept(қабул).
  • Мо code дорем, ки дар ришта кор мекунад Runnable, ки онро қабул намекунад ё барнагардонад. Он як усули ягона дорад - run(давидан).
Чизи дуюми дар хотир доштан дар он аст, ки дар кори худ истеъмолкунандагон ва функсияҳоро CompletalbeFutureистифода мебарад . RunnableБо назардошти ин, шумо ҳамеша метавонед дар хотир доред, ки шумо CompletableFutureин корро карда метавонед:
public static void main(String []args) throws Exception {
        AtomicLong longValue = new AtomicLong(0);
        Runnable task = () -> longValue.set(new Date().getTime());
        Function<Long, Date> dateConverter = (longvalue) -> new Date(longvalue);
        Consumer<Date> printer = date -> {
            System.out.println(date);
            System.out.flush();
        };
        // CompletableFuture computation
        CompletableFuture.runAsync(task)
                         .thenApply((v) -> longValue.get())
                         .thenApply(dateConverter)
                         .thenAccept(printer);
}
Усулҳо versionҳо thenRunдоранд . _ Ин маънои онро дорад, ки ин марҳилаҳо дар риштаи нав иҷро карда мешаванд. Он аз ҳавзи махсус гирифта мешавад, бинобар ин пешакӣ маълум нест, ки он чӣ гуна ҷараён аст, нав ё кӯҳна. Ҳамааш ба он вобаста аст, ки вазифаҳо то чӣ андоза душворанд. Илова ба ин усулҳо, боз се имконоти ҷолиб вуҷуд доранд. Барои равшанӣ, биёед тасаввур кунем, ки мо хидмати муайяне дорем, ки аз ҷое паём қабул мекунад ва ин вақтро мегирад: thenApplythenAcceptAsync
public static class NewsService {
	public static String getMessage() {
		try {
			Thread.currentThread().sleep(3000);
			return "Message";
		} catch (InterruptedException e) {
			throw new IllegalStateException(e);
		}
	}
}
Акнун биёед ба дигар хусусиятҳои он назар андозем CompletableFuture. Мо метавонем натиҷаро CompletableFutureбо натиҷаи дигаре якҷоя кунем CompletableFuture:
Supplier newsSupplier = () -> NewsService.getMessage();

CompletableFuture<String> reader = CompletableFuture.supplyAsync(newsSupplier);
CompletableFuture.completedFuture("!!")
				 .thenCombine(reader, (a, b) -> b + a)
				 .thenAccept(result -> System.out.println(result))
				 .get();
Бояд қайд кард, ки ба таври нобаёнӣ риштаҳо риштаҳои демонӣ хоҳанд буд, аз ин рӯ барои возеҳӣ getмо интизори натиҷаро истифода мебарем. Ва мо метавонем на танҳо якҷоя кунем (якҷоя кунем), балки боз баргардем CompletableFuture:
CompletableFuture.completedFuture(2L)
				.thenCompose((val) -> CompletableFuture.completedFuture(val + 2))
                               .thenAccept(result -> System.out.println(result));
Дар ин ҷо ман мехоҳам қайд намоям, ки барои кӯтоҳ, усул истифода шудааст CompletableFuture.completedFuture. Ин усул риштаи нав эҷод намекунад, бинобар ин қисми боқимондаи занҷир дар ҳамон риштае, ки дар он номида шуда буд, иҷро карда мешавад completedFuture. Усул ҳам ҳаст thenAcceptBoth. Он ба - хеле монанд аст accept, аммо агар thenAccept-ро қабул кунад consumer, thenAcceptBothон гоҳ дигар CompletableStage+ -ро ҳамчун вуруд қабул мекунад BiConsumer, яъне consumer2 манбаъро ҳамчун вуруд қабул мекунад, на як. Боз як имкони ҷолиб бо калима вуҷуд дорад Either: Thread'ом Java не испортишь: Часть IV — Callable, Future и друзья - 3Ин усулҳо алтернативаро қабул мекунанд ва дар ҳамон усуле , ки аввал иҷро мешавад, CompletableStageиҷро карда мешаванд . CompletableStageВа ман мехоҳам ин баррасиро бо як хусусияти ҷолиби дигар CompletableFuture- коркарди хато анҷом диҳам.
CompletableFuture.completedFuture(2L)
				 .thenApply((a) -> {
					throw new IllegalStateException("error");
				 }).thenApply((a) -> 3L)
				 //.exceptionally(ex -> 0L)
				 .thenAccept(val -> System.out.println(val));
Ин code ҳеҷ коре намекунад, зеро... истисно партофта мешавад ва ҳеҷ чиз рӯй нахоҳад дод. Аммо агар мо шарҳ надиҳем exceptionally, мо рафторро муайян мекунем. CompletableFutureМан инчунин тавсия медиҳам, ки видеои зеринро дар ин мавзӯъ тамошо кунед: Ба андешаи хоксоронаи ман, ин видеоҳо аз ҳама визуалӣ дар Интернет мебошанд. Аз онҳо бояд равшан бошад, ки ин ҳама чӣ гуна кор мекунад, мо чӣ арсенал дорем ва чаро ин ҳама лозим аст.

Хулоса

Умедворам, ки ҳоло маълум аст, ки чӣ гуна риштаҳоро барои дарёфти ҳисобҳо пас аз ҳисоб кардани онҳо истифода бурдан мумкин аст. Маводи иловагӣ: #Вячеслав
Шарҳҳо
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION