Try using it in your preferred language.

English

  • English
  • 汉语
  • Español
  • Bahasa Indonesia
  • Português
  • Русский
  • 日本語
  • 한국어
  • Deutsch
  • Français
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Polski
  • Nederlands
  • हिन्दी
  • Magyar
translation

यह एक AI अनुवादित पोस्ट है।

제이온

[स्प्रिंग] @Async का उपयोग कैसे करें

  • लेखन भाषा: कोरियाई
  • आधार देश: सभी देश country-flag

भाषा चुनें

  • हिन्दी
  • English
  • 汉语
  • Español
  • Bahasa Indonesia
  • Português
  • Русский
  • 日本語
  • 한국어
  • Deutsch
  • Français
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Polski
  • Nederlands
  • Magyar

durumis AI द्वारा संक्षेपित पाठ

  • यह लेख एसिंक्रोनस प्रोसेसिंग को लागू करने के तरीके के बारे में बताता है जिसमें @Async एनोटेशन का उपयोग किया जाता है, विशेष रूप से स्प्रिंग में @Async का उपयोग करते समय थ्रेड पूल को कॉन्फ़िगर करने के तरीके पर विस्तार से बताया गया है।
  • इसके अलावा, यह लेख @Async का उपयोग करते समय रिटर्न प्रकार के आधार पर वापसी स्वरूप को Future, ListenableFuture, CompletableFuture आदि में विभाजित करके बताता है और प्रत्येक प्रकार की विशेषताओं और फायदे और नुकसान की तुलनात्मक विश्लेषण करता है।
  • अंत में, यह लेख @Async के फायदे और सावधानियों का परिचय देता है, यह बताता है कि private मेथड में @Async लगाने पर AOP काम नहीं करता है और साथ ही यह भी बताया गया है कि एक ही ऑब्जेक्ट के मेथड को आपस में कॉल करने पर AOP काम नहीं करता है।

जावा अतुल्यकालिक प्रसंस्करण

स्प्रिंग @Async देखने से पहले, सिंक्रोनस, अतुल्यकालिक और मल्टीथ्रेडिंग की अवधारणाएँ अनिवार्य हैं। हम मानते हैं कि आप इन अवधारणाओं से परिचित हैं, और कोड के साथ शुद्ध जावा अतुल्यकालिक प्रसंस्करण विधि पर एक नज़र डालते हैं। यदि आप जावा थ्रेड से परिचित हैं, तो आप इस अध्याय को छोड़ सकते हैं।


public class MessageService {

    public void print(String message) {
        System.out.println(message);
    }
}

public class Main {

    public static void main(String[] args) {
        MessageService messageService = new MessageService();

        for (int i = 1; i <= 100; i++) {
            messageService.print(i + "");
        }
    }


यदि आप संदेश प्राप्त करने और केवल इसे आउटपुट करने की सुविधा को सिंक्रोनस तरीके से बनाते हैं, तो आप ऊपर दिए गए कोड को इस तरह लिख सकते हैं। इसे मल्टीथ्रेडिंग अतुल्यकालिक तरीके से बदलने पर, आप स्रोत कोड को इस तरह लिख सकते हैं।


public class MessageService {

    public void print(String message) {
        new Thread(() -> System.out.println(message))
                .start();
    }
}

public class Main {

    public static void main(String[] args) {
        MessageService messageService = new MessageService();

        for (int i = 1; i <= 100; i++) {
            messageService.print(i + "");
        }
    }


हालाँकि, इस विधि में थ्रेड को प्रबंधित करने में असमर्थता है, जो इसे बहुत खतरनाक बनाता है। उदाहरण के लिए, यदि 10,000 कॉल एक साथ होते हैं, तो आपको बहुत कम समय में 10,000 थ्रेड बनाने होंगे। थ्रेड बनाने की लागत कम नहीं है, इसलिए यह प्रोग्राम के प्रदर्शन को नकारात्मक रूप से प्रभावित करता है, और यहां तक ​​कि OOM त्रुटि भी हो सकती है। इसलिए, थ्रेड को प्रबंधित करने के लिए, आपको थ्रेड पूल को लागू करना होगा, और जावा ExecutorService वर्ग प्रदान करता है।


public class MessageService {

    private final ExecutorService executorService = Executors.newFixedThreadPool(10);

    public void print(String message) {
        executorService.submit(() -> System.out.println(message));
    }
}

public class Main {

    public static void main(String[] args) {
        MessageService messageService = new MessageService();

        for (int i = 1; i <= 100; i++) {
            messageService.print(i + "");
        }
    }


हमने थ्रेड की कुल संख्या को 10 तक सीमित कर दिया है, और अब हम सही ढंग से वांछित मल्टीथ्रेडिंग अतुल्यकालिक प्रसंस्करण कर सकते हैं। हालाँकि, उपरोक्त विधि को अतुल्यकालिक रूप से संसाधित किए जाने वाले प्रत्येक विधि में ExecutorService की submit() विधि लागू करने की आवश्यकता होती है, जिससे बार-बार संशोधन करने पड़ते हैं। दूसरे शब्दों में, यदि आप शुरुआत में सिंक्रोनस लॉजिक के साथ लिखे गए विधि को अतुल्यकालिक में बदलना चाहते हैं, तो विधि के स्वयं के तर्क को बदलना अनिवार्य है।


स्प्रिंग @Async

सरल विधि

@EnableAsync
@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

@Service
public class MessageService {

    @Async
    public void print(String message) {
        System.out.println(message);
    }
}

@RequiredArgsConstructor
@RestController
public class MessageController {

    private final MessageService messageService;

    @GetMapping("/messages")
    @ResponseStatus(code = HttpStatus.OK)
    public void printMessage() {
        for (int i = 1; i <= 100; i++) {
            messageService.print(i + "");
        }
    }


@EnableAsync एनोटेशन को Application क्लास पर रखें, और @Async एनोटेशन को सिंक्रोनस लॉजिक के विधि पर रखें जिसे आप अतुल्यकालिक रूप से संसाधित करना चाहते हैं। लेकिन, इस विधि में थ्रेड को प्रबंधित न करने की समस्या है। ऐसा इसलिए है क्योंकि @Async का डिफ़ॉल्ट कॉन्फ़िगरेशन SimpleAsyncTaskExecutor का उपयोग करना है, जो एक थ्रेड पूल नहीं है, बल्कि केवल थ्रेड बनाने का काम करता है।


थ्रेड पूल का उपयोग करने की विधि

सबसे पहले, Application क्लास से @EnableAsync हटा दें। यदि Application क्लास में @EnableAutoConfiguration या @SpringBootApplication सेटिंग है, तो रनटाइम पर @Configuration के साथ SpringAsyncConfig क्लास (जिसे हम नीचे बनाएंगे) की threadPoolTaskExecutor बीन जानकारी पढ़ी जाएगी।


@Configuration
@EnableAsync // Application नहीं, बल्कि Async सेटिंग क्लास पर लगाना चाहिए।
public class SpringAsyncConfig {

    @Bean(name = "threadPoolTaskExecutor")
    public Executor threadPoolTaskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(3); // डिफ़ॉल्ट थ्रेड की संख्या
        taskExecutor.setMaxPoolSize(30); // अधिकतम थ्रेड की संख्या
        taskExecutor.setQueueCapacity(100); // क्यू आकार
        taskExecutor.setThreadNamePrefix("Executor-");
        return taskExecutor;
    }


आप कोर और मैक्स आकार निर्दिष्ट कर सकते हैं। इस मामले में, यह अनुमान लगाया जा सकता है कि यह शुरू में कोर आकार के रूप में काम करेगा, और यदि यह अधिक काम संभाल नहीं सकता है, तो अधिकतम आकार तक थ्रेड बढ़ जाएगा, लेकिन ऐसा नहीं है।


आंतरिक रूप से, यह Integer.MAX_VALUE आकार का LinkedBlockingQueue बनाता है, इसलिए यदि कोर आकार के थ्रेड काम संभाल नहीं सकते हैं, तो वे क्यू में इंतजार करते हैं। क्यू भरा हुआ होने पर, यह अधिकतम आकार तक थ्रेड बनाता है और काम संभालता है।


यदि आप Integer.MAX_VALUE पर क्यू आकार निर्दिष्ट करने से बचने के लिए, आप queueCapacity निर्दिष्ट कर सकते हैं। ऊपर दिए गए सेटिंग के साथ, यह शुरू में 3 थ्रेड के साथ काम करेगा, और यदि प्रसंस्करण गति धीमी हो जाती है, तो यह कार्य को 100 आकार के क्यू में रख देगा, और यदि कोई और अनुरोध आता है, तो यह अधिकतम 30 थ्रेड बनाएगा और काम संभालेगा।


थ्रेड पूल सेटिंग पूरी हो जाने के बाद, आपको @Async एनोटेशन के साथ विधि में ऊपर दिए गए बीन के नाम को संलग्न करना होगा।


@Service
public class MessageService {

    @Async("threadPoolTaskExecutor")
    public void print(String message) {
        System.out.println(message);
    }


यदि आप कई प्रकार के थ्रेड पूल सेट करना चाहते हैं, तो आपको threadPoolTaskExecutor() जैसी कई बीन बनाने की विधियाँ बनानी होंगी, और @Async सेटिंग करते समय, आप वह थ्रेड पूल बीन डाल सकते हैं जिसे आप चाहते हैं।


रिटर्न टाइप द्वारा लौटाया गया प्रारूप

कोई रिटर्न वैल्यू नहीं है

यह तब होता है जब एक विधि जिसे अतुल्यकालिक रूप से संसाधित किया जाना चाहिए, को प्रसंस्करण परिणाम देने की आवश्यकता नहीं होती है। इस मामले में, आप @Async एनोटेशन का रिटर्न टाइप void पर सेट कर सकते हैं।


रिटर्न वैल्यू है

आप Future, ListenableFuture और CompletableFuture प्रकार को रिटर्न टाइप के रूप में उपयोग कर सकते हैं। आप अतुल्यकालिक विधि के रिटर्न प्रारूप को new AsyncResult() में बांध सकते हैं।


[फ़्यूचर]

@Service
public class MessageService {

    @Async
    public Future print(String message) throws InterruptedException {
        System.out.println("Task Start - " + message);
        Thread.sleep(3000);
        return new AsyncResult<>("jayon-" + message);
    }
}

@RequiredArgsConstructor
@RestController
public class MessageController {

    private final MessageService messageService;

    @GetMapping("/messages")
    @ResponseStatus(code = HttpStatus.OK)
    public void printMessage() throws ExecutionException, InterruptedException {
        for (int i = 1; i <= 5; i++) {
            Future future = messageService.print(i + "");
            System.out.println(future.get());
        }
    }
}

// निष्पादन परिणाम
Task Start - 1
jayon-1
Task Start - 2
jayon-2
Task Start - 3
jayon-3
Task Start - 4
jayon-4
Task Start - 5


future.get() अनुरोध परिणाम के आने तक ब्लॉकिंग के माध्यम से प्रतीक्षा करने का काम करता है। इसलिए यह अतुल्यकालिक ब्लॉकिंग विधि बन जाती है, जिसके परिणामस्वरूप प्रदर्शन खराब होता है। आमतौर पर, फ़्यूचर का उपयोग नहीं किया जाता है।


[ListenableFuture]

@Service
public class MessageService {

    @Async
    public ListenableFuture print(String message) throws InterruptedException {
        System.out.println("Task Start - " + message);
        Thread.sleep(3000);
        return new AsyncResult<>("jayon-" + message);
    }
}

@RequiredArgsConstructor
@RestController
public class MessageController {

    private final MessageService messageService;

    @GetMapping("/messages")
    @ResponseStatus(code = HttpStatus.OK)
    public void printMessage() throws InterruptedException {
        for (int i = 1; i <= 5; i++) {
            ListenableFuture listenableFuture = messageService.print(i + "");
            listenableFuture.addCallback(System.out::println, error -> System.out.println(error.getMessage()));
        }
    }
}

// निष्पादन परिणाम
Task Start - 1
Task Start - 3
Task Start - 2
jayon-1
jayon-2
Task Start - 5
jayon-3
Task Start - 4
jayon-4


ListenableFuture कॉलबैक के माध्यम से गैर-अवरोधक तरीके से कार्यों को संसाधित करने की अनुमति देता है। addCallback() विधि का पहला पैरामीटर कार्य पूरा होने पर कॉलबैक विधि है, और दूसरा पैरामीटर कार्य विफलता पर कॉलबैक विधि है। ध्यान दें कि थ्रेड पूल का कोर थ्रेड 3 पर सेट किया गया है, इसलिए आप देख सकते हैं कि "कार्य प्रारंभ" संदेश शुरू में 3 बार मुद्रित होता है।



[CompletableFuture]

ListenableFuture के साथ भी, आप गैर-अवरोधक तर्क को लागू कर सकते हैं, लेकिन यदि आपको कॉलबैक के अंदर कॉलबैक की आवश्यकता होती है, तो यह बहुत जटिल कोड का कारण बनता है जिसे कॉलबैक नर्क कहा जाता है।


Untitled


बेशक, इस बार हम CompletableFuture को विस्तार से नहीं देखेंगे, इसलिए यदि आप जटिल कॉलबैक को संभालने वाले कोड के बारे में उत्सुक हैं, तो कृपया नीचे दिए गए स्रोत लिंक देखें।


@Service
public class MessageService {

    @Async
    public CompletableFuture print(String message) throws InterruptedException {
        System.out.println("Task Start - " + message);
        Thread.sleep(3000);
        return new AsyncResult<>("jayon-" + message).completable();
    }
}

@RequiredArgsConstructor
@RestController
public class MessageController {

    private final MessageService messageService;

    @GetMapping("/messages")
    @ResponseStatus(code = HttpStatus.OK)
    public void printMessage() throws InterruptedException {
        for (int i = 1; i <= 5; i++) {
            CompletableFuture completableFuture = messageService.print(i + "");
            completableFuture
                    .thenAccept(System.out::println)
                    .exceptionally(error -> {
                        System.out.println(error.getMessage());
                        return null;
                    });
        }
    }


ListenableFuture की कॉलबैक परिभाषा की तुलना में पठनीयता बेहतर है, और यह पूरी तरह से गैर-अवरोधक कार्य करता है। इसलिए, यदि आपको @Async का उपयोग करते समय रिटर्न वैल्यू की आवश्यकता होती है, तो CompletableFuture का उपयोग करने की अनुशंसा की जाती है।


@Async के लाभ

डेवलपर्स सिंक्रोनस तरीके से विधियों को लिख सकते हैं, और यदि वे अतुल्यकालिक चाहते हैं, तो उन्हें बस विधि के ऊपर @Async एनोटेशन जोड़ना होगा। इसलिए, आप सिंक्रोनस और अतुल्यकालिक के लिए अच्छे रखरखाव वाले कोड बना सकते हैं।


@Async के लिए सावधानियां

@Async कार्यक्षमता का उपयोग करने के लिए, आपको @EnableAsync एनोटेशन घोषित करना होगा, लेकिन यदि आप कोई विशेष कॉन्फ़िगरेशन नहीं करते हैं, तो यह प्रॉक्सी मोड में काम करता है। दूसरे शब्दों में, @Async एनोटेशन के साथ काम करने वाली अतुल्यकालिक विधियाँ सभी स्प्रिंग AOP बाधाओं का पालन करती हैं। अधिक जानकारी के लिए, कृपयायह पोस्टदेखें।


  • यदि आप एक निजी विधि पर @Async लगाते हैं, तो AOP काम नहीं करेगा।
  • यदि आप एक ही ऑब्जेक्ट के अंदर विधियों को एक दूसरे को कॉल करते हैं, तो AOP काम नहीं करेगा।


स्रोत

제이온
제이온
제이온
제이온
[जावा] सिंक्रोनाइज़्ड कलेक्शन बनाम कनकरेंट कलेक्शन जावा में सिंक्रोनाइज़्ड कलेक्शन (वेक्टर, हैशटेबल, कलेक्शन्स.सिंक्रोनाइज़्डXXX) मल्टीथ्रेडेड वातावरण में समवर्तीता की गारंटी देते हैं, लेकिन प्रदर्शन में गिरावट और कई ऑपरेशनों को एक साथ उपयोग करते समय समस्याएँ हो सकती हैं। वैकल्पिक रूप से, java.util.concur

25 अप्रैल 2024

[इफ़ेक्टिव जावा] आइटम 6. अनावश्यक ऑब्जेक्ट निर्माण से बचें जावा में अनावश्यक ऑब्जेक्ट निर्माण को कम करके प्रदर्शन को बेहतर बनाने के तरीकों के बारे में बताता है। स्ट्रिंग, बूलियन, रेगुलर एक्सप्रेशन, व्यू ऑब्जेक्ट, ऑटो बॉक्सिंग जैसे विभिन्न उदाहरणों के साथ ऑब्जेक्ट पुन: उपयोग के महत्व पर जोर दिया गया है। खासकर रक्ष

28 अप्रैल 2024

[जावा] रिफ्लेक्शन अवधारणा और उपयोग विधि रिफ्लेक्शन एक एपीआई है जो जावा प्रोग्राम के निष्पादन के दौरान क्लास जानकारी तक पहुंच प्रदान करके क्लास में हेरफेर करने की अनुमति देता है। रनटाइम पर क्लास बनाना और फ़ील्ड और विधियों तक पहुँच प्राप्त करना संभव है, लेकिन ध्यान रहे कि यह एन्कैप्सुलेशन को बाधि

25 अप्रैल 2024

रस्ट कैसे समवर्ती बग को रोकता है रस्ट एक शक्तिशाली भाषा है जो समवर्ती प्रोग्रामिंग की चुनौतियों का समाधान करती है। इसके टाइप सिस्टम और ओनरशिप मॉडल के कारण थ्रेड के बीच डेटा ट्रांसफर और शेयरिंग सुरक्षित है। म्यूटेक्स, चैनल, एटॉमिक जैसे आंतरिक परिवर्तनशीलता पैटर्न का उपयोग करके साझा चर को
곽경직
곽경직
곽경직
곽경직
곽경직

28 मार्च 2024

[Next.js] रनटाइम env इंजेक्शन Next.js में बिल्ड टाइम के बाद पर्यावरण चर सेटिंग के लिए तरीके जानें। विंडोज उपयोगकर्ता भी क्रॉस-एनवी इंस्टॉल करने और स्क्रिप्ट संशोधन विधि को आसानी से पालन कर सकते हैं। स्थानीय, देव, क्यूए, प्रॉड जैसे विभिन्न पर्यावरण चर सेटिंग के लिए इसे कारगर रूप से इस
Sunrabbit
Sunrabbit
Sunrabbit
Sunrabbit

20 मार्च 2024

प्रॉम्प्टिंग गाइड 101 - ग्राहक सेवा यह ब्लॉग पोस्ट बताता है कि Google Workspace के लिए Gemini का उपयोग अपनी ग्राहक सेवा को बेहतर बनाने के लिए कैसे करें, जिसमें मानकीकृत संचार ढाँचे, व्यक्तिगत संचार, प्रशिक्षण सामग्री और बहुत कुछ उत्पन्न करने के लिए प्रॉम्प्ट लिखना शामिल है। पोस्ट में परीक्ष
꿈많은청년들
꿈많은청년들
प्रॉम्प्टिंग गाइड 101
꿈많은청년들
꿈많은청년들

23 मई 2024

निवेश पद्धति (स्टॉक) असीमित खरीद विधि और सात-विभाजन विधि के आधार पर अमेरिकी शेयर ETF में निवेश करने की रणनीति पेश की गई है। स्टॉक चयन, निवेश राशि का विभाजन, खरीद/बिक्री समय निर्धारण, स्वचालित व्यापार प्रणाली का निर्माण जैसे निवेश प्रक्रिया को विस्तार से बताया गया है और 2021 अ
(로또 사는 아빠) 살림 하는 엄마
(로또 사는 아빠) 살림 하는 엄마
(로또 사는 아빠) 살림 하는 엄마
(로또 사는 아빠) 살림 하는 엄마
(로또 사는 아빠) 살림 하는 엄마

20 अप्रैल 2024

भौतिक डेटा मॉडलिंग भौतिक डेटा मॉडलिंग संबंधपरक डेटाबेस की तालिकाओं को वास्तविक उपयोग के लिए डिज़ाइन करने की प्रक्रिया है, जिसमें भंडारण स्थान दक्षता, डेटा विभाजन, इंडेक्स डिज़ाइन आदि शामिल हैं, जिसका उद्देश्य प्रदर्शन अनुकूलन है। धीमी क्वेरी विश्लेषण, इंडेक्स उपयोग, कैशे अन
제이의 블로그
제이의 블로그
제이의 블로그
제이의 블로그
제이의 블로그

9 अप्रैल 2024

[समांतरता] परमाणु संचालन: मेमोरी फेंस और मेमोरी ऑर्डरिंग परमाणु संचालन में मेमोरी क्रम पर विचार करना समवर्ती प्रसंस्करण के लिए आवश्यक है। सीपीयू अनुकूलन के कारण निर्देश क्रम में बदलाव हो सकता है, और यह समवर्ती वातावरण में समस्याएं पैदा कर सकता है। मेमोरी फेंस और ऑर्डरिंग विकल्पों का उपयोग करके इन समस्याओं को हल
곽경직
곽경직
곽경직
곽경직
곽경직

12 अप्रैल 2024