JavaRush /Blog Jawa /Random-JV /Sampeyan ora bisa ngrusak Jawa nganggo thread: Part IV - ...
Viacheslav
tingkat

Sampeyan ora bisa ngrusak Jawa nganggo thread: Part IV - Callable, Future lan kanca-kanca

Diterbitake ing grup

Pambuka

Kita wis ndeleng carane thread digawe ing bagean pisanan . Ayo eling maneh. Sampeyan ora bisa ngrusak Jawa nganggo utas: Part IV - Callable, Future lan kanca - 1Utas iku Threadana sing mlaku run, mula ayo nggunakake kompiler online tutorialspoint java lan nglakokake kode ing ngisor iki:
public class HelloWorld {

    public static void main(String []args){
        Runnable task = () -> {
            System.out.println("Hello World");
        };
        new Thread(task).start();
    }
}
Apa iki mung siji-sijine pilihan kanggo mbukak tugas ing thread?

java.util.concurrent.Callable

Pranyata java.lang.Runnable duwe sedulur lanang jenenge java.util.concurrent.Callable lan lair ing Jawa 1.5. Apa bedane? Yen kita nliti JavaDoc antarmuka iki, kita weruh manawa, ora kaya Runnable, antarmuka anyar nyatakake cara callsing ngasilake asil. Uga, kanthi standar mbuwang Exception. Sing, nyimpen kita saka perlu kanggo nulis try-catchpamblokiran kanggo pangecualian dicenthang. Ora ala wis, ta? Saiki kita duwe Runnabletugas anyar tinimbang:
Callable task = () -> {
	return "Hello, World!";
};
Nanging apa sing kudu dilakoni? Napa kita butuh tugas sing mlaku ing benang sing ngasilake asil? Temenan, ing tembe ngarep-arep bakal nampa asil saka tumindak sing bakal ditindakake ing mangsa ngarep. Future in English - Future. Lan ana antarmuka kanthi jeneng sing padha:java.util.concurrent.Future

java.util.concurrent.Future

Antarmuka java.util.concurrent.Future njlèntrèhaké API kanggo nggarap tugas sing asile bakal dipikolehi ing mangsa ngarep: cara kanggo entuk asil, cara kanggo mriksa status. Kita Futurekasengsem ing implementasine java.util.concurrent.FutureTask . Yaiku Task, iki sing bakal dieksekusi ing Future. Sing uga menarik babagan implementasine iki yaiku ngetrapake lan Runnable. Sampeyan bisa nimbang iki jenis adaptor saka model lawas nggarap tugas ing Utas lan model anyar (anyar ing pangertèn sing katon ing java 1.5). Iki contone:
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());
    }
}
Kaya sing bisa dideleng saka conto, nggunakake metode kita entuk getasil saka masalah task. (!)Penting, yen ing wayahe asil dipikolehi nggunakake metode kasebut, geteksekusi dadi sinkron. Mekanisme apa sampeyan mikir bakal digunakake ing kene? Bener, ora ana blok sinkronisasi - mula kita bakal weruh NUNGGU ing JVisualVM ora minangka monitorutawa wait, nanging minangka sing padha park(amarga mekanisme digunakake LockSupport).

Antarmuka Fungsional

Sabanjure kita bakal pirembagan bab kelas saka Java 1.8, supaya bakal migunani kanggo nggawe introduksi singkat. Ayo ndeleng kode ing ngisor iki:
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);
	}
};
Ana akeh kode sing ora perlu, ta? Saben kelas sing diumumake nindakake fungsi siji, nanging kanggo njlèntrèhaké, kita nggunakake sekumpulan kode tambahan sing ora perlu. Lan para pangembang Jawa uga mikir. Mulane, dheweke ngenalake sakumpulan "antarmuka fungsional" ( @FunctionalInterface) lan mutusake yen saiki Jawa dhewe bakal "mikir" kabeh kanggo kita, kajaba sing penting:
Supplier<String> supplier = () -> "String";
Consumer<String> consumer = s -> System.out.println(s);
Function<String, Integer> converter = s -> Integer.valueOf(s);
Supplier- panyedhiya. Ora ana paramèter, nanging ngasilake barang, yaiku, nyedhiyakake. Consumer- konsumen. Butuh soko minangka input (parameter s) lan nindakake soko karo, sing, nganggo soko. Ana fungsi liyane. Butuh soko minangka input (parameter s), nindakake soko lan ngasilake soko. Kaya sing kita deleng, generik digunakake kanthi aktif. Yen sampeyan ora yakin, sampeyan bisa ngelingi lan maca " Teori generik ing Jawa utawa carane ngetrapake kurung ing praktik ."

CompletableFuture

Sajrone wektu, Java 1.8 ngenalake kelas anyar sing diarani CompletableFuture. Iku ngleksanakake antarmuka Future, tegese kita taskbakal dieksekusi ing mangsa ngarep lan kita bisa nglakokake getlan entuk asil. Nanging dheweke uga nindakake sawetara CompletionStage. Saka terjemahan tujuane wis jelas: iku Tahap tartamtu saka sawetara jinis pitungan. Pambuka ringkes babagan topik kasebut bisa ditemokake ing ringkesan " Introduction to CompletionStage and CompletableFuture ". Ayo langsung menyang titik. Ayo goleki dhaptar metode statis sing kasedhiya kanggo mbantu kita miwiti: Sampeyan ora bisa ngrusak Jawa nganggo utas: Part IV - Callable, Future lan kanca - 2Ing ngisor iki pilihan kanggo nggunakake:
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 "Значение";
        });
    }
}
Yen kita mbukak kode iki, kita bakal weruh sing nggawe CompletableFuturekalebu miwiti kabeh chain. Mulane, nalika ana sawetara podho karo SteamAPI saka Java8, iki prabédan antarane pendekatan iki. Tuladhane:
List<String> array = Arrays.asList("one", "two");
Stream<String> stringStream = array.stream().map(value -> {
	System.out.println("Executed");
	return value.toUpperCase();
});
Iki minangka conto Java 8 Stream Api (sampeyan bisa maca liyane babagan kene " Java 8 Stream API Guide ing Gambar lan Conto "). Yen sampeyan mbukak kode iki, Executedora bakal ditampilake. Yaiku, nalika nggawe stream ing Jawa, stream ora langsung diwiwiti, nanging ngenteni nganti ana nilai sing dibutuhake. Nanging CompletableFuturewiwit chain kanggo eksekusi langsung, tanpa ngenteni kanggo takon kanggo Nilai diwilang. Aku iki penting kanggo ngerti iki. Dadi kita duwe CompletableFuture. Kepiye carane nggawe rantai lan apa sing kita duwe? Ayo elinga babagan antarmuka fungsional sing wis ditulis sadurunge.
  • We duwe fungsi ( Function) sing njupuk A lan ngasilake B. Wis cara siji - apply(aplikasi).
  • Kita duwe konsumen ( Consumer) sing nampa A lan ora ngasilake apa-apa ( Void ). Wis mung siji cara - accept(nampa).
  • Kita duwe kode mlaku ing thread Runnablesing ora nampa utawa bali. Wis siji cara - run(run).
Kapindho sing kudu dielingake yaiku CompletalbeFutureing karyane nggunakake Runnablekonsumen lan fungsi. Amarga iki, sampeyan bisa tansah eling yen sampeyan CompletableFuturebisa nindakake iki:
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);
}
Metode thenRunduwe thenApplyversi . thenAccept_ AsyncIki tegese tahapan kasebut bakal dieksekusi ing thread anyar. Iku bakal dijupuk saka blumbang khusus, supaya ora dingerteni ing advance apa jenis aliran bakal, anyar utawa lawas. Iku kabeh gumantung carane angel tugas. Saliyane cara kasebut, ana telung kemungkinan sing luwih menarik. Kanggo gamblang, ayo bayangake manawa kita duwe layanan tartamtu sing nampa pesen saka endi wae lan butuh wektu:
public static class NewsService {
	public static String getMessage() {
		try {
			Thread.currentThread().sleep(3000);
			return "Message";
		} catch (InterruptedException e) {
			throw new IllegalStateException(e);
		}
	}
}
Saiki, ayo goleki fitur liyane sing CompletableFuture. Kita bisa gabungke asil CompletableFuturekaro asil liyane 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();
Wigati dicathet yen kanthi standar benang bakal dadi benang daemon, supaya luwih jelas get, kita ngenteni asile. Lan kita ora mung bisa nggabungake (gabungan), nanging uga bali CompletableFuture:
CompletableFuture.completedFuture(2L)
				.thenCompose((val) -> CompletableFuture.completedFuture(val + 2))
                               .thenAccept(result -> System.out.println(result));
Ing kene aku pengin nyathet yen kanggo ringkesan, metode kasebut digunakake CompletableFuture.completedFuture. Cara iki ora nggawe utas anyar, mula rantai liyane bakal dieksekusi ing benang sing padha sing diarani completedFuture. Ana uga cara thenAcceptBoth. Iku banget padha karo accept, nanging yen thenAcceptnampa consumer, banjur thenAcceptBothnampa liyane CompletableStage+ minangka input BiConsumer, sing consumer, kang nampa 2 sumber minangka input, ora siji. Ana kemungkinan liyane sing menarik karo tembung Either: Sampeyan ora bisa ngrusak Jawa nganggo utas: Part IV - Callable, Future lan kanca - 3Cara iki nampa alternatif CompletableStagelan bakal dieksekusi ing sing CompletableStagedieksekusi luwih dhisik. Lan aku pengin ngrampungake review iki kanthi fitur sing luwih menarik CompletableFuture- penanganan kesalahan.
CompletableFuture.completedFuture(2L)
				 .thenApply((a) -> {
					throw new IllegalStateException("error");
				 }).thenApply((a) -> 3L)
				 //.exceptionally(ex -> 0L)
				 .thenAccept(val -> System.out.println(val));
Kode iki ora bakal nindakake apa-apa, amarga ... pangecualian bakal dibuwang lan ora bakal kelakon. Nanging yen kita uncomment exceptionally, banjur kita nemtokake prilaku. CompletableFutureAku uga nyaranake nonton video ing ngisor iki babagan topik iki : Ing mratelakake panemume andhap asor, video iki sawetara sing paling visual ing Internet. Iku kudu cetha saka wong-wong mau carane kabeh bisa, apa arsenal kita duwe lan apa iku kabeh perlu.

Kesimpulan

Muga-muga saiki wis jelas kepiye carane benang bisa digunakake kanggo njupuk petungan sawise diitung. Materi tambahan: #Viacheslav
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION