எங்களுக்காக ExecutorServiceஐத் தயாரிக்கும் புதியWorkStealingPool முறையைக் கண்டுபிடிப்போம் .

இந்த நூல் குளம் சிறப்பு வாய்ந்தது. அதன் நடத்தை "திருடுதல்" வேலையின் கருத்தை அடிப்படையாகக் கொண்டது.

பணிகள் வரிசைப்படுத்தப்பட்டு செயலிகளிடையே விநியோகிக்கப்படுகின்றன. ஆனால் ஒரு செயலி பிஸியாக இருந்தால், மற்றொரு இலவச செயலி அதிலிருந்து ஒரு பணியைத் திருடி அதை இயக்க முடியும். பல-திரிக்கப்பட்ட பயன்பாடுகளில் முரண்பாடுகளைக் குறைப்பதற்காக ஜாவாவில் இந்த வடிவம் அறிமுகப்படுத்தப்பட்டது. இது ஃபோர்க்/இணைப்பு கட்டமைப்பில் கட்டப்பட்டுள்ளது .

முட்கரண்டி / சேர

ஃபோர்க்/இணைப்பு கட்டமைப்பில் , பணிகள் மீண்டும் மீண்டும் சிதைந்து, அதாவது அவை துணைப் பணிகளாகப் பிரிக்கப்படுகின்றன. பின்னர் துணைப் பணிகள் தனித்தனியாக செயல்படுத்தப்படுகின்றன, மேலும் துணைப் பணிகளின் முடிவுகள் ஒன்றிணைந்து அசல் பணியின் முடிவை உருவாக்குகின்றன.

ஃபோர்க் முறையானது சில தொடரிழையில் ஒத்திசைவற்ற முறையில் ஒரு பணியைத் தொடங்குகிறது, மேலும் இந்த பணி முடிவடையும் வரை சேரும் முறை உங்களை அனுமதிக்கிறது.

புதிய ஒர்க் ஸ்டீலிங் பூல்

NewWorkStealingPool முறை இரண்டு செயலாக்கங்களைக் கொண்டுள்ளது :

public static ExecutorService newWorkStealingPool(int parallelism) {
        return new ForkJoinPool
            (parallelism,
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
    }

public static ExecutorService newWorkStealingPool() {
        return new ForkJoinPool
            (Runtime.getRuntime().availableProcessors(),
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
    }

ஆரம்பத்தில் இருந்தே, ஹூட்டின் கீழ் நாம் ThreadPoolExecutor கட்டமைப்பாளரை அழைக்கவில்லை என்பதை நாங்கள் கவனிக்கிறோம் . இங்கே நாம் ForkJoinPool நிறுவனத்துடன் வேலை செய்கிறோம் . ThreadPoolExecutor போலவே , இது AbstractExecutorService இன் செயலாக்கமாகும் .

எங்களிடம் தேர்வு செய்ய 2 முறைகள் உள்ளன. முதலாவதாக, நாம் எந்த அளவிலான இணையான நிலையைப் பார்க்க விரும்புகிறோம் என்பதைக் குறிப்பிடுகிறோம். இந்த மதிப்பை நாம் குறிப்பிடவில்லை என்றால், எங்கள் பூலின் இணையான தன்மை ஜாவா மெய்நிகர் கணினியில் கிடைக்கும் செயலி கோர்களின் எண்ணிக்கைக்கு சமமாக இருக்கும்.

இது நடைமுறையில் எவ்வாறு செயல்படுகிறது என்பதைக் கண்டுபிடிக்க வேண்டும்:

Collection<Callable<Void>> tasks = new ArrayList<>();
        ExecutorService executorService = Executors.newWorkStealingPool(10);

        for (int i = 0; i < 10; i++) {
            int taskNumber = i;
            Callable<Void> callable = () -> {
                System.out.println("Processed user request #" + taskNumber + " on thread " + Thread.currentThread().getName());
                return null;
            };
            tasks.add(callable);
        }
        executorService.invokeAll(tasks);

நாங்கள் 10 பணிகளை அவற்றின் சொந்த நிறைவு நிலையைக் காண்பிக்கிறோம். அதன் பிறகு, இன்வோக்ஆல் முறையைப் பயன்படுத்தி அனைத்து பணிகளையும் தொடங்குகிறோம் .

குளத்தில் உள்ள 10 இழைகளில் 10 பணிகளைச் செயல்படுத்தும்போது முடிவுகள்:

ForkJoinPool-1-worker-10 thread இல் செயலாக்கப்பட்ட பயனர் கோரிக்கை #9
ForkJoinPool-1-worker-5 நூல்
செயலாக்கப்பட்ட பயனர் கோரிக்கை #4 இல் ForkJoinPool-1-worker-8 நூல்
செயலாக்கப்பட்ட பயனர் கோரிக்கை #7 ForkJoinPool இல் செயலாக்கப்பட்ட பயனர் கோரிக்கை #1
ForkJoinPool- 1-worker-3 thread இல் 1-worker-2 thread செயலாக்கப்பட்ட பயனர் கோரிக்கை
#2 ForkJoinPool-1-worker-4 நூல்
செயலாக்கப்பட்ட பயனர் கோரிக்கை #3 ForkJoinPool-1-worker-7 நூல்
செயலாக்கப்பட்ட பயனர் கோரிக்கை #6 இல். ForkJoinPool-1-worker-1 thread
இல் கோரிக்கை
#0 செயலாக்கப்பட்டது.

வரிசை உருவான பிறகு, இழைகள் செயல்படுத்துவதற்கான பணிகளை மேற்கொள்வதை நாம் காண்கிறோம். 10 நூல்கள் கொண்ட ஒரு தொகுப்பில் 20 பணிகள் எவ்வாறு விநியோகிக்கப்படும் என்பதையும் நீங்கள் பார்க்கலாம்.

ForkJoinPool-1-worker-4 நூலில் செயலாக்கப்பட்ட
பயனர் கோரிக்கை #3 ForkJoinPool-1-worker-8 நூல்
செயலாக்கப்பட்ட பயனர் கோரிக்கை #7 இல் ForkJoinPool-1-worker-3 நூல்
செயலாக்கப்பட்ட பயனர் கோரிக்கை #2 ForkJoinPool இல் செயலாக்கப்பட்ட பயனர் கோரிக்கை #4-
ForkJoinPool-1-worker-2 நூல் செயலாக்கப்பட்ட பயனர் கோரிக்கை #1 ForkJoinPool
-1-worker-6 நூல்
செயலாக்கப்பட்ட பயனர் கோரிக்கை #8 ForkJoinPool-1-worker-9 நூல்
செயலாக்கப்பட்ட பயனர். ForkJoinPool-1-worker-10 thread
இல் கோரிக்கை #9
செயலாக்கப்பட்டது
. தொழிலாளி-9 நூல்
ForkJoinPool-1-worker-1 நூலில் செயலாக்கப்பட்ட
பயனர் கோரிக்கை #12 ForkJoinPool-1-worker-8 நூல்
செயலாக்கப்பட்ட பயனர் கோரிக்கை #13 இல் ForkJoinPool-1-worker-6 நூல்
செயலாக்கப்பட்ட பயனர் கோரிக்கை #11 ForkJoinPool இல் செயலாக்கப்பட்ட பயனர் கோரிக்கை #15 ForkJoinPool -1-worker-1 thread
செயலாக்கப்பட்ட பயனர் கோரிக்கை #14
ForkJoinPool-1-worker-6 நூல்
செயலாக்கப்பட்ட பயனர் கோரிக்கை #16 ForkJoinPool-1-worker-7 நூல்
செயலாக்கப்பட்ட பயனர் ForkJoinPool-1-worker-6 நூலில் #19
கோரிக்கை செயலாக்கப்பட்ட பயனர் கோரிக்கை #18 ForkJoinPool-1-worker-1 நூலில்

வெளியீட்டில் இருந்து, சில த்ரெட்கள் பல பணிகளைச் செய்து முடிப்பதைக் காணலாம் ( ForkJoinPool-1-worker-6 4 பணிகளை நிறைவுசெய்தது), சில ஒன்றை மட்டும் முடிக்கின்றன ( ForkJoinPool-1-worker-2 ). அழைப்பு முறையைச் செயல்படுத்த 1-வினாடி தாமதம் சேர்க்கப்பட்டால் , படம் மாறும்.

Callable<Void> callable = () -> {
   System.out.println("Processed user request #" + taskNumber + " on thread " + Thread.currentThread().getName());
   TimeUnit.SECONDS.sleep(1);
   return null;
};

பரிசோதனைக்காக, அதே குறியீட்டை மற்றொரு கணினியில் இயக்குவோம். இதன் விளைவாக வரும் வெளியீடு:

ForkJoinPool-1-worker-23 நூலில்
செயலாக்கப்பட்ட பயனர் கோரிக்கை #2 ForkJoinPool-1-worker-31 நூல்
செயலாக்கப்பட்ட பயனர் கோரிக்கை #7 இல் ForkJoinPool-1-worker-27 நூல்
செயலாக்கப்பட்ட பயனர் கோரிக்கை #4 ForkJoinPool இல் செயலாக்கப்பட்டது.
ForkJoinPool-1-worker-19 thread இல் 1-worker-13 thread செயலாக்கப்பட்ட பயனர் கோரிக்கை #0 ForkJoinPool
-1-worker-3 thread இல்
செயலாக்கப்பட்ட பயனர் கோரிக்கை #8 ForkJoinPool-1-worker-21 நூல்
செயலாக்கப்பட்ட பயனர் கோரிக்கை #9 இல். ForkJoinPool-1-worker-17 thread இல்
கோரிக்கை
#6 செயலாக்கப்பட்டது
. தொழிலாளி-23 நூல்
ForkJoinPool-1-worker-19 நூலில் செயலாக்கப்பட்ட
பயனர் கோரிக்கை #15 ForkJoinPool-1-worker-27 நூல்
செயலாக்கப்பட்ட பயனர் கோரிக்கை #14 ForkJoinPool-1-worker-3 நூலில் செயலாக்கப்பட்ட பயனர் கோரிக்கை #11
ForkJoinPool இல் செயலாக்கப்பட்ட பயனர் கோரிக்கை #13
ForkJoinPool -1-worker-31 நூல் செயலாக்கப்பட்ட பயனர் கோரிக்கை #10
ForkJoinPool-1-worker-5 thread இல்
செயலாக்கப்பட்ட பயனர் கோரிக்கை #16 ForkJoinPool-1-worker-9 நூல்
செயலாக்கப்பட்ட பயனர் கோரிக்கை ForkJoinPool-1-worker-21 thread இல் #17
கோரிக்கை செயலாக்கப்பட்ட பயனர் கோரிக்கை #19 ForkJoinPool-1-worker-17 நூலில்

இந்த வெளியீட்டில், குளத்தில் உள்ள நூல்களை நாங்கள் "கேட்டோம்" என்பது குறிப்பிடத்தக்கது. மேலும் என்னவென்றால், தொழிலாளி நூல்களின் பெயர்கள் ஒன்று முதல் பத்து வரை செல்லாது, மாறாக சில நேரங்களில் பத்துக்கும் அதிகமாக இருக்கும். தனித்துவமான பெயர்களைப் பார்க்கும்போது, ​​​​உண்மையில் பத்து தொழிலாளர்கள் (3, 5, 9, 13, 17, 19, 21, 23, 27 மற்றும் 31) இருப்பதைக் காண்கிறோம். இது ஏன் நடந்தது என்று இங்கே கேட்பது மிகவும் நியாயமானதா? என்ன நடக்கிறது என்று உங்களுக்குப் புரியாத போதெல்லாம், பிழைத்திருத்தியைப் பயன்படுத்தவும்.

இதைத்தான் செய்வோம். நடிக்கலாம்நிறைவேற்றுபவர் சேவைForkJoinPool க்கு பொருள் :

final ForkJoinPool forkJoinPool = (ForkJoinPool) executorService;

InvokeAll முறையை அழைத்த பிறகு, இந்த பொருளை ஆய்வு செய்ய, Evaluate Expression செயலைப் பயன்படுத்துவோம் . இதைச் செய்ய, invokeAll முறைக்குப் பிறகு, வெற்று சவுட் போன்ற ஏதேனும் அறிக்கையைச் சேர்த்து, அதன் மீது ஒரு இடைவெளியை அமைக்கவும்.

குளத்தில் 10 இழைகள் இருப்பதைக் காணலாம், ஆனால் வேலை செய்பவர் நூல்களின் வரிசையின் அளவு 32. வித்தியாசமானது, ஆனால் பரவாயில்லை. தோண்டிக்கொண்டே இருப்போம். ஒரு குளத்தை உருவாக்கும் போது, ​​இணையான நிலையை 32க்கு மேல் அமைக்க முயற்சிப்போம், 40 என்று சொல்லுங்கள்.

ExecutorService executorService = Executors.newWorkStealingPool(40);

பிழைத்திருத்தத்தில், என்பதை பார்க்கலாம்forkJoinPool பொருள் மீண்டும்.

இப்போது தொழிலாளர் நூல்களின் வரிசையின் அளவு 128. இது JVM இன் உள் மேம்படுத்தல்களில் ஒன்று என்று நாம் கருதலாம். அதை ஜேடிகே (openjdk-14) குறியீட்டில் கண்டுபிடிக்க முயற்சிப்போம்:

நாங்கள் சந்தேகித்தது போலவே: இணையான மதிப்பில் பிட்வைஸ் கையாளுதல்களைச் செய்வதன் மூலம் தொழிலாளி நூல்களின் வரிசையின் அளவு கணக்கிடப்படுகிறது. இங்கே சரியாக என்ன நடக்கிறது என்பதைக் கண்டுபிடிக்க நாம் முயற்சிக்க வேண்டியதில்லை. அத்தகைய தேர்வுமுறை உள்ளது என்பதை எளிமையாக அறிந்தால் போதும்.

எங்கள் எடுத்துக்காட்டின் மற்றொரு சுவாரஸ்யமான அம்சம் invokeAll முறையைப் பயன்படுத்துவதாகும் . invokeAll முறையானது ஒரு முடிவையோ அல்லது முடிவுகளின் பட்டியலையோ (எங்கள் விஷயத்தில், ஒரு பட்டியல்<எதிர்காலம்<Void>>) கொடுக்க முடியும் என்பது குறிப்பிடத்தக்கது , இதில் ஒவ்வொரு பணியின் முடிவையும் காணலாம்.

var results = executorService.invokeAll(tasks);
        for (Future<Void> result : results) {
            // Process the task's result
        }

இந்த சிறப்பு வகையான சேவை மற்றும் நூல் குளம் ஆகியவை யூகிக்கக்கூடிய அல்லது குறைந்தபட்சம் மறைமுகமான, ஒத்திசைவு நிலையுடன் பணிகளில் பயன்படுத்தப்படலாம்.