உங்களுக்கு எக்ஸிகியூட்டர் இடைமுகம் ஏன் தேவை?

ஜாவா 5 க்கு முன், உங்கள் பயன்பாட்டில் உங்கள் சொந்த குறியீடு நூல் மேலாண்மை அனைத்தையும் எழுத வேண்டும். கூடுதலாக, உருவாக்குதல் ஏபுதிய நூல்ஆப்ஜெக்ட் என்பது ஒரு வள-தீவிர செயல்பாடாகும், மேலும் ஒவ்வொரு இலகுவான பணிக்கும் ஒரு புதிய நூலை உருவாக்குவதில் அர்த்தமில்லை. மல்டி-த்ரெட் அப்ளிகேஷன்களின் ஒவ்வொரு டெவலப்பருக்கும் இந்த சிக்கல் நன்கு தெரிந்திருப்பதால், இந்த செயல்பாட்டை ஜாவாவில் எக்ஸிகியூட்டர் கட்டமைப்பாகக் கொண்டு வர அவர்கள் முடிவு செய்தனர் .

என்ன பெரிய யோசனை? இது எளிதானது: ஒவ்வொரு புதிய பணிக்கும் ஒரு புதிய நூலை உருவாக்குவதற்குப் பதிலாக, நூல்கள் ஒரு வகையான "சேமிப்பகத்தில்" வைக்கப்படுகின்றன, மேலும் புதிய பணி வரும்போது, ​​புதிய ஒன்றை உருவாக்குவதற்குப் பதிலாக ஏற்கனவே உள்ள நூலை மீட்டெடுக்கிறோம்.

இந்த கட்டமைப்பின் முக்கிய இடைமுகங்கள் எக்ஸிகியூட்டர் , எக்ஸிகியூட்டர் சர்வீஸ் மற்றும் ஷெட்யூல்டு எக்ஸிகியூட்டர் சர்வீஸ் ஆகும் , இவை ஒவ்வொன்றும் முந்தைய செயல்பாட்டின் செயல்பாட்டை நீட்டிக்கிறது.

எக்ஸிகியூட்டர் இடைமுகம் அடிப்படை இடைமுகம். இது இயங்கக்கூடிய பொருளால் செயல்படுத்தப்படும் ஒற்றை வெற்றிடத்தை இயக்கும் (இயக்கக்கூடிய கட்டளை) முறையை அறிவிக்கிறது .

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

முறை விளக்கம்
வெற்றிட பணிநிறுத்தம் (); இந்த முறையை அழைப்பது ExecutorService ஐ நிறுத்துகிறது . செயலாக்கத்திற்காக ஏற்கனவே சமர்ப்பிக்கப்பட்ட அனைத்து பணிகளும் முடிக்கப்படும், ஆனால் புதிய பணிகள் ஏற்றுக்கொள்ளப்படாது.
பட்டியல்<Runnable> shutdownNow();

இந்த முறையை அழைப்பது ExecutorService ஐ நிறுத்துகிறது . செயலாக்கத்திற்காக ஏற்கனவே சமர்ப்பிக்கப்பட்ட அனைத்து பணிகளுக்கும் Thread.interrupt அழைக்கப்படும். இந்த முறை வரிசைப்படுத்தப்பட்ட பணிகளின் பட்டியலை வழங்குகிறது.

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

எச்சரிக்கை: இந்த முறையை அழைப்பது ஆதாரங்களைக் கசியவிடலாம்.

பூலியன் isShutdown(); ExecutorService நிறுத்தப்பட்டுள்ளதா என்பதைச் சரிபார்க்கிறது .
பூலியன் isTerminated(); ExecutorService நிறுத்தப்பட்டதைத் தொடர்ந்து அனைத்து பணிகளும் முடிந்தால் உண்மை எனத் திரும்பும் . shutdown() அல்லது shutdownNow() என்று அழைக்கப்படும் வரை , அது எப்போதும் தவறானதாகத் திரும்பும் .
பூலியன் காத்திருப்பு முடித்தல் (நீண்ட நேரம் முடிந்தது, டைம்யூனிட் அலகு) குறுக்கீடு விதிவிலக்கு;

பணிநிறுத்தம்() முறை அழைக்கப்பட்ட பிறகு , பின்வரும் நிபந்தனைகளில் ஒன்று உண்மையாகும் வரை இந்த முறை அது அழைக்கப்படும் நூலைத் தடுக்கிறது:

  • திட்டமிடப்பட்ட அனைத்து பணிகளும் முடிந்தன;
  • முறைக்கு அனுப்பப்பட்ட காலக்கெடு கடந்துவிட்டது;
  • தற்போதைய நூல் தடைபட்டது.

எல்லாப் பணிகளும் முடிந்தால் சரி என்றும், முடிவடைவதற்கு முன் காலக்கெடு முடிந்தால் தவறு என்றும் வழங்கும் .

<T> எதிர்கால <T> சமர்ப்பி (அழைக்கக்கூடிய<T> பணி);

ExecutorService இல் அழைக்கக்கூடிய பணியைச் சேர்க்கிறது மற்றும் எதிர்கால இடைமுகத்தை செயல்படுத்தும் ஒரு பொருளை வழங்குகிறது .

<T> என்பது நிறைவேற்றப்பட்ட பணியின் முடிவின் வகை.

<T> எதிர்கால <T> சமர்ப்பி (இயக்கக்கூடிய பணி, டி முடிவு);

ExecutorService இல் இயங்கக்கூடிய பணியைச் சேர்க்கிறது மற்றும் எதிர்கால இடைமுகத்தை செயல்படுத்தும் ஒரு பொருளை வழங்குகிறது .

T முடிவு அளவுரு என்பது பெறு() முறைக்கு அழைப்பின் மூலம் திரும்பப் பெறப்படும்எதிர்கால பொருள்.

எதிர்கால<?> சமர்ப்பிக்கவும் (இயக்கக்கூடிய பணி);

ExecutorService இல் இயங்கக்கூடிய பணியைச் சேர்க்கிறது மற்றும் எதிர்கால இடைமுகத்தை செயல்படுத்தும் ஒரு பொருளை வழங்குகிறது .

விளைந்த எதிர்கால பொருளில் get() முறையை அழைத்தால் , நாம் பூஜ்யத்தைப் பெறுகிறோம்.

<T> பட்டியல்<எதிர்கால<T>> invokeAll(சேகரிப்பு<? அழைக்கக்கூடிய<T>> பணிகளை நீட்டிக்கிறது) InterruptedException ஐ வீசுகிறது;

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

முறை இயங்கும் போது பணி சேகரிப்பு மாற்றப்பட்டால், இந்த முறையின் முடிவு வரையறுக்கப்படாமல் இருக்கும் .

<T> பட்டியல்<எதிர்கால<T>> invokeAll(சேகரிப்பு<? அழைக்கக்கூடிய<T>> பணிகளை நீட்டிக்கிறது, நீண்ட நேரம் முடிந்தது, TimeUnit அலகு) InterruptedException ஐ வீசுகிறது;

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

காலக்கெடு முடிந்தால், முடிக்கப்படாத பணிகள் ரத்து செய்யப்படும்.

குறிப்பு: ரத்து செய்யப்பட்ட பணி இயங்குவதை நிறுத்தாமல் போகலாம் (இந்த பக்க விளைவை எடுத்துக்காட்டில் பார்ப்போம்).

முறை இயங்கும் போது பணி சேகரிப்பு மாற்றப்பட்டால், இந்த முறையின் முடிவு வரையறுக்கப்படாமல் இருக்கும் .

<T> T invokeAny(சேகரிப்பு<? அழைக்கக்கூடிய<T>> பணிகளை நீட்டிக்கிறது) InterruptedException, ExecutionException;

அழைக்கக்கூடிய பணிகளின் பட்டியலை ExecutorService க்கு அனுப்புகிறது . விதிவிலக்கு இல்லாமல் (ஏதேனும் இருந்தால்) முடிக்கப்பட்ட பணிகளில் ஒன்றின் முடிவை (ஏதேனும் இருந்தால்) வழங்கும்.

முறை இயங்கும் போது பணி சேகரிப்பு மாற்றப்பட்டால், இந்த முறையின் முடிவு வரையறுக்கப்படாமல் இருக்கும் .

<T> T invokeAny(சேகரிப்பு<? அழைக்கக்கூடிய<T>> பணிகளை நீட்டிக்கிறது, நீண்ட நேரம் முடிந்தது, TimeUnit அலகு) InterruptedException, ExecutionException, TimeoutException ஆகியவற்றை வீசுகிறது;

அழைக்கக்கூடிய பணிகளின் பட்டியலை ExecutorService க்கு அனுப்புகிறது . முறைக்கு அனுப்பப்பட்ட காலக்கெடு முடிவதற்குள் விதிவிலக்கு இல்லாமல் முடிக்கப்பட்ட பணிகளில் ஒன்றின் முடிவை (ஏதேனும் இருந்தால்) வழங்கும்.

முறை இயங்கும் போது பணி சேகரிப்பு மாற்றப்பட்டால், இந்த முறையின் முடிவு வரையறுக்கப்படாமல் இருக்கும் .

ExecutorService உடன் பணிபுரிவதற்கான ஒரு சிறிய உதாரணத்தைப் பார்ப்போம் .


import java.util.List;
import java.util.concurrent.*;

public class ExecutorServiceTest {
   public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
//Create an ExecutorService for 2 threads
       java.util.concurrent.ExecutorService executorService = new ThreadPoolExecutor(2, 2, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10));
// Create 5 tasks
       MyRunnable task1 = new MyRunnable();
       MyRunnable task2 = new MyRunnable();
       MyRunnable task3 = new MyRunnable();
       MyRunnable task4 = new MyRunnable();
       MyRunnable task5 = new MyRunnable();

       final List<MyRunnable> tasks = List.of(task1, task2, task3, task4, task5);
// Pass a list that contains the 5 tasks we created
       final List<Future<Void>> futures = executorService.invokeAll(tasks, 6, TimeUnit.SECONDS);
       System.out.println("Futures received");

// Stop the ExecutorService
       executorService.shutdown();

       try {
           TimeUnit.SECONDS.sleep(3);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       System.out.println(executorService.isShutdown());
       System.out.println(executorService.isTerminated());
   }

   public static class MyRunnable implements Callable<Void> {

       @Override
       public void call() {
// Add 2 delays. When the ExecutorService is stopped, we will see which delay is in progress when the attempt is made to stop execution of the task
           try {
               TimeUnit.SECONDS.sleep(3);
           } catch (InterruptedException e) {
               System.out.println("sleep 1: " + e.getMessage());
           }
           try {
               TimeUnit.SECONDS.sleep(2);
           } catch (InterruptedException e) {
               System.out.println("sleep 2: " + e.getMessage());
           }
           System.out.println("done");
           return null;
       }
   }
}

வெளியீடு:

முடிந்தது எதிர்காலத்திற்கு தூக்கம் கிடைத்தது
1 : தூக்கம் தடைபட்டது தூக்கம் 1: தூக்கம் தடைபட்டது செய்தது உண்மை உண்மை






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

நிரல் துவங்கிய ஆறு வினாடிகளுக்குப் பிறகு, இன்வோக் ஆல் மெத்தட் காலாவதியானது மற்றும் முடிவு எதிர்காலங்களின் பட்டியலாக வழங்கப்படும் . ஃப்யூச்சர்ஸ் பெறப்பட்ட வெளியீட்டு சரத்திலிருந்து இதைக் காணலாம் .

முதல் இரண்டு பணிகள் முடிந்ததும், மேலும் இரண்டு பணிகள் தொடங்கும். ஆனால் invokeAll முறையில் அமைக்கப்பட்ட காலக்கெடு முடிவடைந்ததால், இந்த இரண்டு பணிகளையும் முடிக்க நேரம் இல்லை. அவர்கள் "ரத்து" கட்டளையைப் பெறுகிறார்கள். அதனால்தான் வெளியீடு ஸ்லீப் 1 உடன் இரண்டு வரிகளைக் கொண்டுள்ளது: தூக்கம் குறுக்கிடப்பட்டது .

பின்னர் முடிந்தவுடன் மேலும் இரண்டு வரிகளைக் காணலாம் . invokeAll முறையை விவரிக்கும் போது நான் குறிப்பிட்ட பக்க விளைவு இதுவாகும் .

ஐந்தாவது மற்றும் இறுதிப் பணி தொடங்கப்படவே இல்லை, எனவே வெளியீட்டில் அதைப் பற்றி எதையும் காண முடியாது.

கடைசி இரண்டு வரிகள் isShutdown மற்றும் isTerminated முறைகளை அழைப்பதன் விளைவாகும் .

இந்த உதாரணத்தை பிழைத்திருத்த பயன்முறையில் இயக்குவதும், காலக்கெடு முடிந்ததும் பணி நிலையைப் பார்ப்பதும் சுவாரஸ்யமானது ( executorService.shutdown() ;

இரண்டு பணிகள் சாதாரணமாக முடிந்ததையும் , மூன்று பணிகள் "ரத்து" செய்யப்பட்டதையும் காண்கிறோம் .

திட்டமிடப்பட்ட நிறைவேற்று சேவை

நிறைவேற்றுபவர்கள் பற்றிய எங்கள் விவாதத்தை முடிக்க, ScheduledExecutorService ஐப் பார்ப்போம் .

இது 4 முறைகளைக் கொண்டுள்ளது:

முறை விளக்கம்
பொது ScheduledFuture<?> அட்டவணை (இயக்கக்கூடிய கட்டளை, நீண்ட தாமதம், TimeUnit அலகு); வாதமாக குறிப்பிடப்பட்ட தாமதத்திற்குப் பிறகு ஒருமுறை இயக்க, நிறைவேற்றப்பட்ட இயக்கக்கூடிய பணியை திட்டமிடுகிறது .
பொது <V> ScheduledFuture<V> அட்டவணை (அழைக்கக்கூடிய<V> அழைக்கக்கூடியது, நீண்ட தாமதம், TimeUnit அலகு); வாதமாக குறிப்பிடப்பட்ட தாமதத்திற்குப் பிறகு ஒருமுறை இயக்க, நிறைவேற்றப்பட்ட அழைக்கக்கூடிய பணியை திட்டமிடுகிறது.
பொது ScheduledFuture<?> அட்டவணைAtFixedRate(இயக்கக்கூடிய கட்டளை, நீண்ட ஆரம்ப தாமதம், நீண்ட காலம், TimeUnit அலகு); நிறைவேற்றப்பட்ட பணியை குறிப்பிட்ட கால இடைவெளியில் செயல்படுத்த திட்டமிடுகிறது, இது ஆரம்ப தாமதத்திற்குப் பிறகு முதல் முறையாகச் செயல்படுத்தப்படும் , மேலும் ஒவ்வொரு அடுத்தடுத்த ஓட்டமும் காலத்திற்குப் பிறகு தொடங்கும் .
பொது ScheduledFuture<?> அட்டவணைWithFixedDelay(இயக்கக்கூடிய கட்டளை, நீண்ட ஆரம்ப தாமதம், நீண்ட தாமதம், TimeUnit அலகு); நிறைவேற்றப்பட்ட பணியை குறிப்பிட்ட கால இடைவெளியில் செயல்படுத்த திட்டமிடுகிறது, இது ஆரம்ப தாமதத்திற்குப் பிறகு முதல் முறையாகச் செயல்படுத்தப்படும் , மேலும் ஒவ்வொரு அடுத்த ஓட்டமும் தாமதத்திற்குப் பிறகு தொடங்கும் (முந்தைய ரன் முடிந்ததற்கும் தற்போதைய தொடக்கத்திற்கும் இடைப்பட்ட காலம்).