அறிமுகம்
பகுதி I இல் , நூல்கள் எவ்வாறு உருவாக்கப்படுகின்றன என்பதை மதிப்பாய்வு செய்தோம். இன்னொரு முறை நினைவு கூர்வோம்.
![ஒன்றாகச் சிறந்தது: ஜாவா மற்றும் நூல் வகுப்பு. பகுதி IV - அழைக்கக்கூடிய, எதிர்காலம் மற்றும் நண்பர்கள் - 1]()
ஒரு நூல் திரி வகுப்பால் குறிப்பிடப்படுகிறது, அதன்
run()
முறை அழைக்கப்படுகிறது.
எனவே டுடோரியல்ஸ்பாயிண்ட் ஆன்லைன் ஜாவா கம்பைலரைப் பயன்படுத்தி பின்வரும் குறியீட்டை இயக்குவோம்:
public class HelloWorld {
public static void main(String[] args) {
Runnable task = () -> {
System.out.println("Hello World");
};
new Thread(task).start();
}
}
ஒரு நூலில் பணியைத் தொடங்குவதற்கான ஒரே வழி இதுதானா?
java.util.concurrent.அழைக்கக்கூடியது
java.lang.Runnable இல் ஜாவா 1.5 இல் உலகிற்கு வந்த
java.util.concurrent.Callable என்று அழைக்கப்படும் ஒரு சகோதரர் இருக்கிறார் . வேறுபாடுகள் என்ன? இந்த இடைமுகத்திற்கான Javadoc ஐ நீங்கள் உற்று நோக்கினால்,
Runnable
புதிய இடைமுகம்
call()
ஒரு முடிவை வழங்கும் முறையைப் போலல்லாமல், ஒரு முறையை அறிவிக்கிறது. மேலும், இது முன்னிருப்பாக விதிவிலக்கை வீசுகிறது. அதாவது,
try-catch
சரிபார்க்கப்பட்ட விதிவிலக்குகளைத் தடுப்பதில் இருந்து நம்மைக் காப்பாற்றுகிறது. மோசமாக இல்லை, இல்லையா? இப்போது எங்களிடம் புதிய பணி உள்ளது
Runnable
:
Callable task = () -> {
return "Hello, World!";
};
ஆனால் நாம் அதை என்ன செய்வது? முடிவை வழங்கும் நூலில் இயங்கும் பணி நமக்கு ஏன் தேவை? வெளிப்படையாக, எதிர்காலத்தில் செய்யப்படும் எந்தவொரு செயல்களுக்கும், எதிர்காலத்தில் அந்த செயல்களின் முடிவைப் பெறுவோம் என்று எதிர்பார்க்கிறோம். தொடர்புடைய பெயருடன் எங்களிடம் ஒரு இடைமுகம் உள்ளது:
java.util.concurrent.Future
java.util.concurrent.எதிர்காலம்
java.util.concurrent.Future இடைமுகமானது பணிகளுடன் பணிபுரிவதற்கான API ஐ வரையறுக்கிறது,
அதன் முடிவுகளை நாம் எதிர்காலத்தில் பெற திட்டமிட்டுள்ளோம்: முடிவைப் பெறுவதற்கான முறைகள் மற்றும் நிலையை சரிபார்க்கும் முறைகள். பற்றி ,
java.util.concurrent.FutureTaskFuture
வகுப்பில் அதை செயல்படுத்துவதில் நாங்கள் ஆர்வமாக உள்ளோம் . இல் செயல்படுத்தப்படும் "பணி" இதுதான் . இந்த செயலாக்கத்தை இன்னும் சுவாரஸ்யமாக்குவது என்னவென்றால், இது Runnable ஐயும் செயல்படுத்துகிறது. நூல்களில் பணிகளுடன் பணிபுரியும் பழைய மாதிரிக்கும் புதிய மாதிரிக்கும் (ஜாவா 1.5 இல் தோன்றிய பொருளில் புதியது) இதை நீங்கள் ஒரு வகையான அடாப்டராகக் கருதலாம். இங்கே ஒரு உதாரணம்:
Future
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
பணியின் முடிவைப் பெற நாங்கள் முறையைப் பயன்படுத்துகிறோம்.
குறிப்பு:முறையைப் பயன்படுத்தி முடிவைப் பெறும்போது
get()
, செயல்படுத்தல் ஒத்திசைவாகும்! இங்கே என்ன பொறிமுறையைப் பயன்படுத்த வேண்டும் என்று நினைக்கிறீர்கள்? உண்மை, ஒத்திசைவு தொகுதி இல்லை.
அதனால்தான் JVisualVM இல் காத்திருப்பதை ஒரு
monitor
அல்லது
wait
, ஆனால் பழக்கமான
park()
முறையாக (
LockSupport
பொறிமுறை பயன்படுத்தப்படுவதால்) பார்க்க மாட்டோம் .
செயல்பாட்டு இடைமுகங்கள்
அடுத்து, ஜாவா 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);
}
};
நிறைய மற்றும் நிறைய கூடுதல் குறியீடு, நீங்கள் சொல்ல மாட்டீர்களா? அறிவிக்கப்பட்ட வகுப்புகள் ஒவ்வொன்றும் ஒரு செயல்பாட்டைச் செய்கிறது, ஆனால் அதை வரையறுக்க கூடுதல் துணைக் குறியீட்டைப் பயன்படுத்துகிறோம். ஜாவா டெவலப்பர்கள் இப்படித்தான் நினைத்தார்கள். அதன்படி, அவர்கள் "செயல்பாட்டு இடைமுகங்களின்" ( ) தொகுப்பை அறிமுகப்படுத்தி
@FunctionalInterface
, இப்போது ஜாவாவே "சிந்தனையை" செய்யும் என்று முடிவு செய்தனர், மேலும் நாம் கவலைப்பட வேண்டிய முக்கியமான விஷயங்களை மட்டும் விட்டுவிடுகிறார்கள்:
Supplier<String> supplier = () -> "String";
Consumer<String> consumer = s -> System.out.println(s);
Function<String, Integer> converter = s -> Integer.valueOf(s);
ஒரு
Supplier
பொருட்கள். இதற்கு அளவுருக்கள் இல்லை, ஆனால் அது எதையாவது வழங்குகிறது. இப்படித்தான் பொருட்களை வழங்குகிறது. A
Consumer
நுகர்கிறது. இது எதையாவது உள்ளீடாக (ஒரு வாதம்) எடுத்து அதைக் கொண்டு ஏதாவது செய்கிறது. அது எதை உட்கொள்கிறது என்பதுதான் வாதம். பிறகு நமக்கும் உண்டு
Function
. இது உள்ளீடுகளை (வாதங்கள்) எடுக்கிறது, எதையாவது செய்கிறது மற்றும் எதையாவது திரும்பப் பெறுகிறது. நாங்கள் ஜெனரிக்ஸை தீவிரமாகப் பயன்படுத்துவதை நீங்கள் பார்க்கலாம்.
உங்களுக்குத் தெரியாவிட்டால், " ஜாவாவில் ஜெனரிக்ஸ்: நடைமுறையில் கோண அடைப்புக்குறிகளை எவ்வாறு பயன்படுத்துவது " என்பதைப் படிப்பதன் மூலம் புதுப்பிப்பைப் பெறலாம் .
முடிக்கக்கூடிய எதிர்காலம்
CompletableFuture
நேரம் கடந்து, ஜாவா 1.8 இல் ஒரு புதிய வகுப்பு தோன்றியது. இது இடைமுகத்தை செயல்படுத்துகிறது
Future
, அதாவது எதிர்காலத்தில் எங்கள் பணிகள் முடிக்கப்படும், மேலும்
get()
முடிவைப் பெற நாம் அழைக்கலாம். ஆனால் இது இடைமுகத்தையும் செயல்படுத்துகிறது
CompletionStage
. பெயர் அனைத்தையும் கூறுகிறது: இது சில கணக்கீடுகளின் ஒரு குறிப்பிட்ட கட்டமாகும். தலைப்பைப் பற்றிய சுருக்கமான அறிமுகத்தை இங்கே உள்ள மதிப்பாய்வில் காணலாம்: நிறைவுநிலை மற்றும் நிறைவடையக்கூடிய எதிர்காலத்திற்கான அறிமுகம். சரி விஷயத்துக்கு வருவோம். தொடங்குவதற்கு உதவும் நிலையான முறைகளின் பட்டியலைப் பார்ப்போம்:
![ஒன்றாகச் சிறந்தது: ஜாவா மற்றும் நூல் வகுப்பு. பகுதி IV - அழைக்கக்கூடிய, எதிர்காலம் மற்றும் நண்பர்கள் - 2]()
அவற்றைப் பயன்படுத்துவதற்கான விருப்பங்கள் இங்கே:
import java.util.concurrent.CompletableFuture;
public class App {
public static void main(String[] args) throws Exception {
// A CompletableFuture that already contains a Result
CompletableFuture<String> completed;
completed = CompletableFuture.completedFuture("Just a value");
// A CompletableFuture that runs a new thread from Runnable. That's why it's Void
CompletableFuture<Void> voidCompletableFuture;
voidCompletableFuture = CompletableFuture.runAsync(() -> {
System.out.println("run " + Thread.currentThread().getName());
});
// A CompletableFuture that starts a new thread whose result we'll get from a Supplier
CompletableFuture<String> supplier;
supplier = CompletableFuture.supplyAsync(() -> {
System.out.println("supply " + Thread.currentThread().getName());
return "Value";
});
}
}
இந்தக் குறியீட்டை இயக்கினால், ஒரு முழு பைப்லைனையும் தொடங்குவதை உள்ளடக்கியதை உருவாக்குவதைக் காண்போம்
CompletableFuture
. எனவே, Java8 இலிருந்து SteamAPI உடன் ஒரு குறிப்பிட்ட ஒற்றுமையுடன், இந்த அணுகுமுறைகளுக்கு இடையேயான வித்தியாசத்தை நாம் இங்கு காணலாம். உதாரணத்திற்கு:
List<String> array = Arrays.asList("one", "two");
Stream<String> stringStream = array.stream().map(value -> {
System.out.println("Executed");
return value.toUpperCase();
});
இது ஜாவா 8 இன் ஸ்ட்ரீம் ஏபிஐக்கு ஒரு எடுத்துக்காட்டு. இந்தக் குறியீட்டை இயக்கினால், "செயல்படுத்தப்பட்டது" காட்டப்படாது என்பதைக் காண்பீர்கள். வேறு வார்த்தைகளில் கூறுவதானால், ஜாவாவில் ஒரு ஸ்ட்ரீம் உருவாக்கப்பட்டால், ஸ்ட்ரீம் உடனடியாக தொடங்காது. மாறாக, அதிலிருந்து ஒரு மதிப்பை யாராவது விரும்புவதற்காக அது காத்திருக்கிறது. ஆனால்
CompletableFuture
யாரோ ஒரு மதிப்பைக் கேட்கும் வரை காத்திருக்காமல், உடனடியாக பைப்லைனை இயக்கத் தொடங்குகிறது. இதைப் புரிந்துகொள்வது முக்கியம் என்று நினைக்கிறேன். எஸ் ஓ, எங்களிடம் ஒரு
CompletableFuture
. நாம் எப்படி ஒரு பைப்லைனை (அல்லது சங்கிலியை) உருவாக்கலாம் மற்றும் நம்மிடம் என்ன வழிமுறைகள் உள்ளன? நாங்கள் முன்பு எழுதிய அந்த செயல்பாட்டு இடைமுகங்களை நினைவுகூருங்கள்.
- எங்களிடம் உள்ளது
Function
, அது A ஐ எடுத்து B ஐ வழங்கும். அதற்கு ஒற்றை முறை உள்ளது: apply()
.
- எங்களிடம் உள்ளது
Consumer
, அது A ஐ எடுக்கும் மற்றும் எதையும் திரும்பப் பெறாது (வெற்று). இது ஒரு ஒற்றை முறையைக் கொண்டுள்ளது: accept()
.
- எங்களிடம் உள்ளது
Runnable
, இது நூலில் இயங்குகிறது, மேலும் எதையும் எடுத்துக்கொண்டு எதையும் திருப்பித் தராது. இது ஒரு ஒற்றை முறையைக் கொண்டுள்ளது: run()
.
நினைவில் கொள்ள வேண்டிய அடுத்த விஷயம் என்னவென்றால் , , மற்றும் அதன் வேலையில்
CompletableFuture
பயன்படுத்துகிறது . அதன்படி, பின்வருவனவற்றை நீங்கள் செய்ய முடியும் என்பதை நீங்கள் எப்போதும் அறிந்து கொள்ளலாம் :
Runnable
Consumers
Functions
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);
}
, , மற்றும் முறைகள் "Async" பதிப்புகளைக் கொண்டுள்ளன
thenRun()
. இதன் பொருள் இந்த நிலைகள் வேறு திரியில் முடிக்கப்படும். இந்த நூல் ஒரு சிறப்புக் குளத்தில் இருந்து எடுக்கப்படும் — எனவே இது புதியதா அல்லது பழைய நூலா என்பதை முன்கூட்டியே அறிய மாட்டோம். இது அனைத்தும் பணிகள் எவ்வளவு கணக்கீட்டு ரீதியாக தீவிரமானவை என்பதைப் பொறுத்தது. இந்த முறைகளுக்கு கூடுதலாக, இன்னும் மூன்று சுவாரஸ்யமான சாத்தியங்கள் உள்ளன. தெளிவுக்காக, எங்கிருந்தோ சில வகையான செய்திகளைப் பெறும் ஒரு குறிப்பிட்ட சேவை எங்களிடம் உள்ளது என்று கற்பனை செய்து கொள்வோம் - இதற்கு நேரம் எடுக்கும்:
thenApply()
thenAccept()
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()
முடிவுக்காக காத்திருக்கிறோம். நாம் ஒன்றிணைப்பது மட்டுமல்லாமல்
CompletableFutures
, பின்வருவனவற்றையும் திரும்பப் பெறலாம்
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
உள்ளீடாக ஏற்றுக்கொள்கிறது, அதாவது
consumer
ஒன்றுக்கு பதிலாக 2 ஆதாரங்களை எடுக்கும் a. "ஒன்று" என்ற வார்த்தையை உள்ளடக்கிய முறைகளால் வழங்கப்படும் மற்றொரு சுவாரஸ்யமான திறன் உள்ளது:
![ஒன்றாகச் சிறந்தது: ஜாவா மற்றும் நூல் வகுப்பு. பகுதி IV - அழைக்கக்கூடிய, எதிர்காலம் மற்றும் நண்பர்கள் - 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));
இந்த குறியீடு எதுவும் செய்யாது, ஏனென்றால் விதிவிலக்கு இருக்கும், வேறு எதுவும் நடக்காது. ஆனால் "விதிவிலக்காக" அறிக்கையை கருத்துத் தெரிவிக்காமல், எதிர்பார்க்கப்படும் நடத்தையை வரையறுக்கிறோம். பற்றி பேசுகையில்
CompletableFuture
, பின்வரும் வீடியோவைப் பார்க்கவும் பரிந்துரைக்கிறேன்:
எனது தாழ்மையான கருத்துப்படி, இவை இணையத்தில் மிகவும் விளக்கமான வீடியோக்களில் ஒன்றாகும். இவை அனைத்தும் எவ்வாறு செயல்படுகின்றன, எங்களிடம் என்ன கருவித்தொகுப்பு உள்ளது, இவை அனைத்தும் ஏன் தேவை என்பதை அவர்கள் தெளிவுபடுத்த வேண்டும்.
முடிவுரை
த்ரெட்கள் முடிந்த பிறகு கணக்கீடுகளைப் பெற எப்படி த்ரெட்களைப் பயன்படுத்தலாம் என்பது இப்போது தெளிவாகத் தெரிகிறது. கூடுதல் பொருள்:
ஒன்றாகச் சிறந்தது: ஜாவா மற்றும் நூல் வகுப்பு. பகுதி I — செயல்படுத்தும் நூல்கள் ஒன்றாகச் சிறப்பாகச் செயல்படுகின்றன: ஜாவா மற்றும் நூல் வகுப்பு. பகுதி II - ஒன்றாக ஒத்திசைத்தல் சிறந்தது: ஜாவா மற்றும் நூல் வகுப்பு. பகுதி III — ஒன்றாகச் செயல்படுவது சிறந்தது: ஜாவா மற்றும் த்ரெட் வகுப்பு. பகுதி V - எக்ஸிகியூட்டர், த்ரெட்பூல், ஃபோர்க்/சேர் பெட்டர் பெட்டர்: ஜாவா மற்றும் த்ரெட் கிளாஸ். பகுதி VI - நெருப்பு!
GO TO FULL VERSION