खोज…


परिचय

एक परफ़ॉर्मर और डेटा-संचालित एप्लिकेशन बनाते समय, सम-विषम कार्यों में समय-गहन कार्यों को पूरा करने और समवर्ती रूप से कई कार्यों को करने के लिए बहुत मददगार हो सकता है। यह विषय समवर्ती कई कार्यों को समवर्ती रूप से पूरा करने के लिए ThreadPoolExecutors का उपयोग करने की अवधारणा को पेश करेगा।

अतुल्यकालिक कार्य निष्पादित करना, जहां कोई वापसी मूल्य नहीं है, जो एक रननीय श्रेणी के उदाहरण का उपयोग करने की आवश्यकता है

कुछ एप्लिकेशन तथाकथित "फायर एंड फॉरगेट" कार्यों को बनाना चाहते हैं, जिन्हें समय-समय पर ट्रिगर किया जा सकता है और उन्हें असाइन किए गए कार्य के पूरा होने पर लौटाए गए किसी भी प्रकार के मूल्य को वापस करने की आवश्यकता नहीं है (उदाहरण के लिए, पुरानी अस्थायी फ़ाइलों को शुद्ध करना, लॉग्स को घुमाना, ऑटोबाफ्ट करना राज्य)।

इस उदाहरण में, हम दो कक्षाएं बनाएंगे: एक जो रननेबल इंटरफ़ेस को लागू करता है, और एक जिसमें एक मुख्य () विधि शामिल है।

AsyncMaintenanceTaskCompleter.java

import lombok.extern.java.Log;

import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

@Log
public class AsyncMaintenanceTaskCompleter implements Runnable {
    private int taskNumber;

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

    public void run() {
        int timeout = ThreadLocalRandom.current().nextInt(1, 20);
        try {
            log.info(String.format("Task %d is sleeping for %d seconds", taskNumber, timeout));
            TimeUnit.SECONDS.sleep(timeout);
            log.info(String.format("Task %d is done sleeping", taskNumber));

        } catch (InterruptedException e) {
            log.warning(e.getMessage());
        }
    }
}

AsyncExample1

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class AsyncExample1 {
    public static void main(String[] args){
        ExecutorService executorService = Executors.newCachedThreadPool();
        for(int i = 0; i < 10; i++){
            executorService.execute(new AsyncMaintenanceTaskCompleter(i));
        }
        executorService.shutdown();
    }
}

निम्नलिखित आउटपुट में AsyncExample1.main () चल रहा है:

Dec 28, 2016 2:21:03 PM AsyncMaintenanceTaskCompleter run
INFO: Task 8 is sleeping for 18 seconds
Dec 28, 2016 2:21:03 PM AsyncMaintenanceTaskCompleter run
INFO: Task 6 is sleeping for 4 seconds
Dec 28, 2016 2:21:03 PM AsyncMaintenanceTaskCompleter run
INFO: Task 2 is sleeping for 6 seconds
Dec 28, 2016 2:21:03 PM AsyncMaintenanceTaskCompleter run
INFO: Task 3 is sleeping for 4 seconds
Dec 28, 2016 2:21:03 PM AsyncMaintenanceTaskCompleter run
INFO: Task 9 is sleeping for 14 seconds
Dec 28, 2016 2:21:03 PM AsyncMaintenanceTaskCompleter run
INFO: Task 4 is sleeping for 9 seconds
Dec 28, 2016 2:21:03 PM AsyncMaintenanceTaskCompleter run
INFO: Task 5 is sleeping for 10 seconds
Dec 28, 2016 2:21:03 PM AsyncMaintenanceTaskCompleter run
INFO: Task 0 is sleeping for 7 seconds
Dec 28, 2016 2:21:03 PM AsyncMaintenanceTaskCompleter run
INFO: Task 1 is sleeping for 9 seconds
Dec 28, 2016 2:21:03 PM AsyncMaintenanceTaskCompleter run
INFO: Task 7 is sleeping for 8 seconds
Dec 28, 2016 2:21:07 PM AsyncMaintenanceTaskCompleter run
INFO: Task 6 is done sleeping
Dec 28, 2016 2:21:07 PM AsyncMaintenanceTaskCompleter run
INFO: Task 3 is done sleeping
Dec 28, 2016 2:21:09 PM AsyncMaintenanceTaskCompleter run
INFO: Task 2 is done sleeping
Dec 28, 2016 2:21:10 PM AsyncMaintenanceTaskCompleter run
INFO: Task 0 is done sleeping
Dec 28, 2016 2:21:11 PM AsyncMaintenanceTaskCompleter run
INFO: Task 7 is done sleeping
Dec 28, 2016 2:21:12 PM AsyncMaintenanceTaskCompleter run
INFO: Task 4 is done sleeping
Dec 28, 2016 2:21:12 PM AsyncMaintenanceTaskCompleter run
INFO: Task 1 is done sleeping
Dec 28, 2016 2:21:13 PM AsyncMaintenanceTaskCompleter run
INFO: Task 5 is done sleeping
Dec 28, 2016 2:21:17 PM AsyncMaintenanceTaskCompleter run
INFO: Task 9 is done sleeping
Dec 28, 2016 2:21:21 PM AsyncMaintenanceTaskCompleter run
INFO: Task 8 is done sleeping

Process finished with exit code 0

नोट का अवलोकन: ऊपर दिए गए आउटपुट में ध्यान देने योग्य कई बातें हैं,

  1. कार्यों का पूर्वानुमान क्रम में निष्पादित नहीं हुआ।
  2. चूँकि प्रत्येक कार्य एक (छद्म) यादृच्छिक समय के लिए सो रहा था, वे जरूरी नहीं कि जिस क्रम में उनका आह्वान किया गया था, उसमें पूरा नहीं हुआ हो।

अतुल्यकालिक कार्य करना जहां एक रिटर्न वैल्यू की आवश्यकता होती है जो एक कॉल करने योग्य क्लास इंस्टेंस का उपयोग कर रहा है

लंबे समय तक चलने वाले कार्य को निष्पादित करना और पूरा होने के बाद उस कार्य के परिणाम का उपयोग करना अक्सर आवश्यक होता है।

इस उदाहरण में, हम दो कक्षाएं बनाएंगे: एक जो कॉल करने योग्य <T> इंटरफ़ेस को लागू करता है (जहां T वह प्रकार है जिसे हम वापस करना चाहते हैं), और एक जिसमें एक मुख्य () विधि है।

AsyncValueTypeTaskCompleter.java

import lombok.extern.java.Log;

import java.util.concurrent.Callable;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

@Log
public class AsyncValueTypeTaskCompleter implements Callable<Integer> {
    private int taskNumber;

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

    @Override
    public Integer call() throws Exception {
        int timeout = ThreadLocalRandom.current().nextInt(1, 20);
        try {
            log.info(String.format("Task %d is sleeping", taskNumber));
            TimeUnit.SECONDS.sleep(timeout);
            log.info(String.format("Task %d is done sleeping", taskNumber));

        } catch (InterruptedException e) {
            log.warning(e.getMessage());
        }
        return timeout;
    }
}

AsyncExample2.java

import lombok.extern.java.Log;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

@Log
public class AsyncExample2 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        List<Future<Integer>> futures = new ArrayList<>();
        for (int i = 0; i < 10; i++){
            Future<Integer> submittedFuture = executorService.submit(new AsyncValueTypeTaskCompleter(i));
            futures.add(submittedFuture);
        }
        executorService.shutdown();
        while(!futures.isEmpty()){
            for(int j = 0; j < futures.size(); j++){
                Future<Integer> f = futures.get(j);
                if(f.isDone()){
                    try {
                        int timeout = f.get();
                        log.info(String.format("A task just completed after sleeping for %d seconds", timeout));
                        futures.remove(f);
                    } catch (InterruptedException | ExecutionException e) {
                        log.warning(e.getMessage());
                    }
                }
            }
        }
    }
}

निम्नलिखित आउटपुट में AsyncExample2.main () चल रहा है:

Dec 28, 2016 3:07:15 PM AsyncValueTypeTaskCompleter call
INFO: Task 7 is sleeping
Dec 28, 2016 3:07:15 PM AsyncValueTypeTaskCompleter call
INFO: Task 8 is sleeping
Dec 28, 2016 3:07:15 PM AsyncValueTypeTaskCompleter call
INFO: Task 2 is sleeping
Dec 28, 2016 3:07:15 PM AsyncValueTypeTaskCompleter call
INFO: Task 1 is sleeping
Dec 28, 2016 3:07:15 PM AsyncValueTypeTaskCompleter call
INFO: Task 4 is sleeping
Dec 28, 2016 3:07:15 PM AsyncValueTypeTaskCompleter call
INFO: Task 9 is sleeping
Dec 28, 2016 3:07:15 PM AsyncValueTypeTaskCompleter call
INFO: Task 0 is sleeping
Dec 28, 2016 3:07:15 PM AsyncValueTypeTaskCompleter call
INFO: Task 6 is sleeping
Dec 28, 2016 3:07:15 PM AsyncValueTypeTaskCompleter call
INFO: Task 5 is sleeping
Dec 28, 2016 3:07:15 PM AsyncValueTypeTaskCompleter call
INFO: Task 3 is sleeping
Dec 28, 2016 3:07:16 PM AsyncValueTypeTaskCompleter call
INFO: Task 8 is done sleeping
Dec 28, 2016 3:07:16 PM AsyncExample2 main
INFO: A task just completed after sleeping for 1 seconds
Dec 28, 2016 3:07:17 PM AsyncValueTypeTaskCompleter call
INFO: Task 2 is done sleeping
Dec 28, 2016 3:07:17 PM AsyncExample2 main
INFO: A task just completed after sleeping for 2 seconds
Dec 28, 2016 3:07:17 PM AsyncValueTypeTaskCompleter call
INFO: Task 9 is done sleeping
Dec 28, 2016 3:07:17 PM AsyncExample2 main
INFO: A task just completed after sleeping for 2 seconds
Dec 28, 2016 3:07:19 PM AsyncValueTypeTaskCompleter call
INFO: Task 3 is done sleeping
Dec 28, 2016 3:07:19 PM AsyncExample2 main
INFO: A task just completed after sleeping for 4 seconds
Dec 28, 2016 3:07:20 PM AsyncValueTypeTaskCompleter call
INFO: Task 0 is done sleeping
Dec 28, 2016 3:07:20 PM AsyncExample2 main
INFO: A task just completed after sleeping for 5 seconds
Dec 28, 2016 3:07:21 PM AsyncValueTypeTaskCompleter call
INFO: Task 5 is done sleeping
Dec 28, 2016 3:07:21 PM AsyncExample2 main
INFO: A task just completed after sleeping for 6 seconds
Dec 28, 2016 3:07:25 PM AsyncValueTypeTaskCompleter call
INFO: Task 1 is done sleeping
Dec 28, 2016 3:07:25 PM AsyncExample2 main
INFO: A task just completed after sleeping for 10 seconds
Dec 28, 2016 3:07:27 PM AsyncValueTypeTaskCompleter call
INFO: Task 6 is done sleeping
Dec 28, 2016 3:07:27 PM AsyncExample2 main
INFO: A task just completed after sleeping for 12 seconds
Dec 28, 2016 3:07:29 PM AsyncValueTypeTaskCompleter call
INFO: Task 7 is done sleeping
Dec 28, 2016 3:07:29 PM AsyncExample2 main
INFO: A task just completed after sleeping for 14 seconds
Dec 28, 2016 3:07:31 PM AsyncValueTypeTaskCompleter call
INFO: Task 4 is done sleeping
Dec 28, 2016 3:07:31 PM AsyncExample2 main
INFO: A task just completed after sleeping for 16 seconds

नोट के अवलोकन:

उपरोक्त आउटपुट में ध्यान देने योग्य कई बातें हैं,

  1. ExecutorService.submit () के लिए प्रत्येक कॉल ने भविष्य का एक उदाहरण लौटाया, जिसे बाद में उपयोग के लिए एक सूची में संग्रहीत किया गया था
  2. भविष्य में एक विधि होती है जिसे डोडोन () कहा जाता है, जिसका उपयोग यह जांचने के लिए किया जा सकता है कि क्या हमारा कार्य वापसी मूल्य की जांच करने का प्रयास करने से पहले पूरा हो गया है। फ्यूचर पर Future.get () पद्धति को कॉल करना जो अभी तक नहीं किया गया है, कार्य पूरा होने तक वर्तमान थ्रेड को ब्लॉक कर देगा, संभवतः कार्य को अतुल्यकालिक प्रदर्शन करने से प्राप्त कई लाभों को नकार देगा।
  3. निष्पादक सेवा / शटडाउन () विधि को भविष्य की वस्तुओं के रिटर्न मूल्यों की जांच करने से पहले बुलाया गया था। यह आवश्यक नहीं है, लेकिन यह दिखाने के लिए इस तरह से किया गया था कि यह संभव है। निष्पादक सेवा। शटडाउन () विधि उन कार्यों को पूरा करने से नहीं रोकती है जो पहले से एक्ज़ीक्यूसर सर्विस में प्रस्तुत किए गए हैं, बल्कि नए कार्यों को कतार में शामिल होने से रोकता है।

लैम्बदास का उपयोग करते हुए अतुल्यकालिक टास्क इनलाइन को परिभाषित करना

जबकि अच्छा सॉफ्टवेयर डिज़ाइन अक्सर कोड पुन: प्रयोज्य को अधिकतम करता है, कभी-कभी कोड रीडेबिलिटी को अधिकतम करने के लिए लैम्बडा अभिव्यक्तियों के माध्यम से आपके कोड में अतुल्यकालिक कार्यों को इनलाइन को परिभाषित करना उपयोगी हो सकता है।

इस उदाहरण में, हम एक एकल वर्ग बनाएंगे जिसमें एक मुख्य () विधि है। इस पद्धति के अंदर, हम कॉल करने योग्य और रन करने योग्य <T> के उदाहरणों को बनाने और निष्पादित करने के लिए लैम्ब्डा अभिव्यक्तियों का उपयोग करेंगे।

AsyncExample3.java

import lombok.extern.java.Log;

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

@Log
public class AsyncExample3 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        List<Future<Integer>> futures = new ArrayList<>();
        for(int i = 0; i < 5; i++){
            final int index = i;
            executorService.execute(() -> {
                int timeout = getTimeout();
                log.info(String.format("Runnable %d has been submitted and will sleep for %d seconds", index, timeout));
                try {
                    TimeUnit.SECONDS.sleep(timeout);
                } catch (InterruptedException e) {
                    log.warning(e.getMessage());
                }
                log.info(String.format("Runnable %d has finished sleeping", index));
            });
            Future<Integer> submittedFuture = executorService.submit(() -> {
                int timeout = getTimeout();
                log.info(String.format("Callable %d will begin sleeping", index));
                try {
                    TimeUnit.SECONDS.sleep(timeout);
                } catch (InterruptedException e) {
                    log.warning(e.getMessage());
                }
                log.info(String.format("Callable %d is done sleeping", index));
                return timeout;
            });
            futures.add(submittedFuture);
        }
        executorService.shutdown();
        while(!futures.isEmpty()){
            for(int j = 0; j < futures.size(); j++){
                Future<Integer> f = futures.get(j);
                if(f.isDone()){
                    try {
                        int timeout = f.get();
                        log.info(String.format("A task just completed after sleeping for %d seconds", timeout));
                        futures.remove(f);
                    } catch (InterruptedException | ExecutionException e) {
                        log.warning(e.getMessage());
                    }
                }
            }
        }
    }

    public static int getTimeout(){
        return ThreadLocalRandom.current().nextInt(1, 20);
    }
}

नोट के अवलोकन:

उपरोक्त आउटपुट में ध्यान देने योग्य कई बातें हैं,

  1. लैम्ब्डा एक्सप्रेशंस में वेरिएबल्स और मेथड्स का उपयोग होता है जो उस स्कोप के लिए उपलब्ध हैं जिसमें वे परिभाषित किए गए हैं, लेकिन लैम्ब्डा एक्सप्रेशन के अंदर उपयोग के लिए सभी वेरिएबल्स फाइनल (या प्रभावी रूप से फाइनल) होने चाहिए।
  2. हमें यह निर्दिष्ट करने की आवश्यकता नहीं है कि हमारी लैम्ब्डा अभिव्यक्ति एक कॉल करने योग्य है या एक चलने योग्य <टी> स्पष्ट रूप से, वापसी प्रकार स्वचालित रूप से रिटर्न प्रकार से अनुमानित है।


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow