1 தொடருக்கான எக்ஸிகியூட்டர் சர்வீஸ் ஏன் தேவைப்படலாம்?

நீங்கள் Executors.newSingleThreadExecutor முறையைப் பயன்படுத்தி , ஒரே நூலை உள்ளடக்கிய ஒரு பூல் மூலம் ExecutorService ஐ உருவாக்கலாம் . குளத்தின் தர்க்கம் பின்வருமாறு:

  • சேவை ஒரு நேரத்தில் ஒரு பணியை மட்டுமே செய்கிறது.
  • செயல்பாட்டிற்கு N பணிகளைச் சமர்ப்பித்தால், அனைத்து N பணிகளும் ஒற்றை நூல் மூலம் ஒன்றன் பின் ஒன்றாக செயல்படுத்தப்படும்.
  • தொடரிழை குறுக்கிடப்பட்டால், மீதமுள்ள பணிகளைச் செய்ய புதிய நூல் உருவாக்கப்படும்.

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

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

பயனர் கோரிக்கையைச் செயலாக்குவதற்கு ஒரு பணி வகுப்பை உருவாக்குகிறோம்:


class Task implements Runnable {
   private final int taskNumber;

   public Task(int taskNumber) {
       this.taskNumber = taskNumber;
   }

   @Override
   public void run() {
       try {
           Thread.sleep(1000);
       } catch (InterruptedException ignored) {
       }
       System.out.printf("Processed request #%d on thread id=%d\\n", taskNumber, Thread.currentThread().getId());
   }
}
    

உள்வரும் கோரிக்கையைச் செயலாக்கும் நடத்தையை வகுப்பு மாதிரியாக்கி அதன் எண்ணைக் காட்டுகிறது.

அடுத்து, பிரதான முறையில், 1 தொடருக்கான ExecutorService ஐ உருவாக்குகிறோம் , உள்வரும் கோரிக்கைகளை வரிசையாகச் செயல்படுத்த இதைப் பயன்படுத்துவோம். பணி நிபந்தனைகள் "30 வினாடிகளுக்குள்" விதிக்கப்படுவதால், நாங்கள் 30-வினாடி காத்திருப்பைச் சேர்த்து, பின்னர் ExecutorService ஐ வலுக்கட்டாயமாக நிறுத்துகிறோம் .


public static void main(String[] args) throws InterruptedException {
   ExecutorService executorService = Executors.newSingleThreadExecutor();

   for (int i = 0; i < 1_000; i++) {
       executorService.execute(new Task(i));
   }
   executorService.awaitTermination(30, TimeUnit.SECONDS);
   executorService.shutdownNow();
}
    

நிரலைத் தொடங்கிய பிறகு, கன்சோல் கோரிக்கை செயலாக்கத்தைப் பற்றிய செய்திகளைக் காட்டுகிறது:

த்ரெட் ஐடியில் செயலாக்கப்பட்ட கோரிக்கை #0=16
த்ரெட் ஐடியில் செயலாக்கப்பட்ட கோரிக்கை #1=16
செயலாக்கப்பட்ட கோரிக்கை #2 த்ரெட்டில் ஐடி=16

செயலாக்கப்பட்ட கோரிக்கை #29 த்ரெட் ஐடியில்=16

கோரிக்கைகளை 30 வினாடிகள் செயலாக்கிய பிறகு, executorService shutdownNow() முறையை அழைக்கிறது , இது தற்போதைய பணியை (செயல்படுத்தப்படுவது) நிறுத்தி, நிலுவையில் உள்ள அனைத்து பணிகளையும் ரத்து செய்கிறது. அதன் பிறகு, நிரல் வெற்றிகரமாக முடிவடைகிறது.

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

இதைச் செய்ய, பணிகளில் ஒன்று செயல்படுத்தப்படும்போது, ​​பாதுகாப்பற்ற மற்றும் காலாவதியான Thread.currentThread().stop() முறையைப் பயன்படுத்தி எங்கள் நூலை நிறுத்துகிறோம். பணிகளில் ஒன்று நூலை நிறுத்தும் சூழ்நிலையை உருவகப்படுத்துவதற்காக நாங்கள் வேண்டுமென்றே இதைச் செய்கிறோம்.

பணி வகுப்பில் ரன் முறையை மாற்றுவோம் :


@Override
public void run() {
   try {
       Thread.sleep(1000);
   } catch (InterruptedException ignored) {
   }

   if (taskNumber == 5) {
       Thread.currentThread().stop();
   }

   System.out.printf("Processed request #%d on thread id=%d\\n", taskNumber, Thread.currentThread().getId());
}
    

பணி எண் 5 இல் குறுக்கிடுவோம்.

பணி #5 முடிவில் நூல் குறுக்கிடப்பட்டதன் மூலம் வெளியீடு எப்படி இருக்கும் என்று பார்ப்போம்:

த்ரெட் ஐடியில் செயலாக்கப்பட்ட கோரிக்கை #0=16
த்ரெட் ஐடியில் செயலாக்கப்பட்ட கோரிக்கை #1=16
செயலாக்கப்பட்ட கோரிக்கை #2 த்ரெட் ஐடியில்=16
செயலாக்கப்பட்ட கோரிக்கை #3 த்ரெட் ஐடியில்=16
செயலாக்கப்பட்ட கோரிக்கை #4 த்ரெட் ஐடியில்=16
செயலாக்கப்பட்ட கோரிக்கை #6 ஆன் நூல் ஐடி = 17
த்ரெட் ஐடி = 17 இல் செயலாக்கப்பட்ட கோரிக்கை #7

செயலாக்கப்பட்ட கோரிக்கை #29 நூல் ஐடி = 17

பணி 5 இன் முடிவில் த்ரெட் குறுக்கிடப்பட்ட பிறகு, பணிகள் 17 ஐ அடையாளங்காட்டியில் செயல்படுத்தப்படத் தொடங்குகின்றன, இருப்பினும் அவை முன்பு 16 ஐக் கொண்ட த்ரெட்டில் செயல்படுத்தப்பட்டிருந்தாலும், எங்கள் பூலில் ஒரு ஒற்றை நூல், இது ஒரு விஷயத்தை மட்டுமே குறிக்கும்: executorService நிறுத்தப்பட்ட நூலை புதியதாக மாற்றியது மற்றும் பணிகளை தொடர்ந்து செயல்படுத்துகிறது.

எனவே, ஒரு நேரத்தில் ஒருமுறை மட்டுமே பணிகளைச் செயல்படுத்த விரும்பும்போது ஒற்றை-நூல் குளத்துடன் newSingleThreadExecutor ஐப் பயன்படுத்த வேண்டும் , மேலும் முந்தைய பணி முடிந்தாலும் (எ.கா. எங்கள் பணிகள் நூலைக் கொல்கின்றன).

நூல் தொழிற்சாலை

நூல்களை உருவாக்குவது மற்றும் மீண்டும் உருவாக்குவது பற்றி பேசும்போது, ​​​​குறிப்பிடாமல் இருக்க முடியாதுநூல் தொழிற்சாலை.

நூல் தொழிற்சாலைதேவைக்கேற்ப புதிய இழைகளை உருவாக்கும் ஒரு பொருளாகும்.

எங்களுடைய சொந்த நூல் உருவாக்கும் தொழிற்சாலையை உருவாக்கி அதன் உதாரணத்தை Executors.newSingleThreadExecutor (ThreadFactory threadFactory) முறைக்கு அனுப்பலாம்.


ExecutorService executorService = Executors.newSingleThreadExecutor(new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r, "MyThread");
            }
        });
                    
ஒரு புதிய நூலை உருவாக்கும் முறையை நாங்கள் மேலெழுதுகிறோம், ஒரு நூலின் பெயரை கட்டமைப்பாளருக்கு அனுப்புகிறோம்.

ExecutorService executorService = Executors.newSingleThreadExecutor(new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r, "MyThread");
                thread.setPriority(Thread.MAX_PRIORITY);
                return thread;
            }
        });
                    
உருவாக்கப்பட்ட நூலின் பெயரையும் முன்னுரிமையையும் மாற்றியுள்ளோம்.

எனவே எங்களிடம் 2 ஓவர்லோடட் Executors.newSingleThreadExecutor முறைகள் இருப்பதைக் காண்கிறோம் . ஒன்று அளவுருக்கள் இல்லாமல், இரண்டாவது ஒரு ThreadFactory அளவுருவுடன்.

ஒரு ThreadFactory ஐப் பயன்படுத்தி , நீங்கள் உருவாக்கிய நூல்களை தேவைக்கேற்ப கட்டமைக்கலாம், எடுத்துக்காட்டாக, முன்னுரிமைகளை அமைப்பதன் மூலம், நூல் துணைப்பிரிவுகளைப் பயன்படுத்துவதன் மூலம், நூலில் ஒரு UncaughtExceptionHandler ஐச் சேர்ப்பதன் மூலம், மற்றும் பல.