এক্সিকিউটর সার্ভিস ব্যবহার করে কীভাবে সমস্ত থ্রেড শেষ হওয়ার অপেক্ষা করবেন?


381

আমাকে একবারে 4 টি পরিমাণ কাজ সম্পাদন করতে হবে, এরকম কিছু:

ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
while(...) {
    taskExecutor.execute(new MyTask());
}
//...wait for completion somehow

সবগুলি সম্পূর্ণ হয়ে গেলে আমি কীভাবে বিজ্ঞপ্তি পেতে পারি? আপাতত আমি কিছু গ্লোবাল টাস্ক কাউন্টার স্থাপনের চেয়ে ভাল কিছু সম্পর্কে ভাবতে পারি না এবং প্রতিটি কাজের শেষে এটিকে হ্রাস করতে পারি, তারপরে এই কাউন্টারটিকে 0 হওয়ার জন্য অসীম লুপে নজর রাখুন; বা ফিউচারের একটি তালিকা পান এবং অসীম লুপ মনিটরে তাদের সবার জন্যই হয়। অসীম লুপগুলিকে জড়িত না করা এর চেয়ে ভাল সমাধানগুলি কী?

ধন্যবাদ।

উত্তর:


446

মূলত ExecutorServiceআপনি কল করার shutdown()পরে এবং তারপরে awaitTermination():

ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
while(...) {
  taskExecutor.execute(new MyTask());
}
taskExecutor.shutdown();
try {
  taskExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
  ...
}

9
এই ঠিক কি হরতাল / awaitTermination জন্য বোঝানো হয়
অনুজ্জ্বল খ

31
যদি এই টাস্ক হ্যান্ডলিংটি এককালীন ইভেন্ট হয় তবে এটি একটি ভাল প্যাটার্ন। যদি এটি একই রানটাইমের সময় বারবার করা হয় তবে এটি সর্বোত্তম নয়, কারণ প্রতিবার সঞ্চালিত হওয়ার সময় আপনি বারবার থ্রেড তৈরি এবং ছিঁড়ে ফেলবেন।
sjlee

44
আমি এমন কোনও অফিসিয়াল ডকুমেন্টেশন খুঁজছি যা Long.MAX_VALUE, TimeUnit.NANOSECONDSটাইমআউট না করার সমতুল্য।
স্যাম হারওয়েল

15
আমি বিশ্বাস করতে পারি না যে সমস্ত বর্তমান থ্রেডে যোগ দিতে আপনাকে শাটডাউন ব্যবহার করতে হবে (শাটডাউন ব্যবহারের পরে, আপনি আর কখনও নির্বাহক ব্যবহার করতে পারবেন না)। পরিবর্তে ভবিষ্যতের তালিকা ব্যবহার করার পরামর্শ দিন ...
রোজারডপ্যাক

20
@ সামহরওয়েল অংশটির অধীনে java.util.concurrentপ্যাকেজ ডকুমেন্টেশনটি দেখুন Timing: "চিরকাল" অপেক্ষা করতে, আপনিLong.MAX_VALUE
আগস্টে 'বেলুচিনের

174

একটি কাউন্টডাউনল্যাচ ব্যবহার করুন :

CountDownLatch latch = new CountDownLatch(totalNumberOfTasks);
ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
while(...) {
  taskExecutor.execute(new MyTask());
}

try {
  latch.await();
} catch (InterruptedException E) {
   // handle
}

এবং আপনার কার্যের মধ্যে (চেষ্টা / শেষ পর্যন্ত ঘের)

latch.countDown();

3
4 টি কাজ নেই। এখানে "কিছু সংখ্যক কাজ" করা হয়েছে যা একবারে 4 হয়।
ক্লিটাস

2
দুঃখিত, আমি প্রশ্নটি ভুল বুঝেছি। হ্যাঁ, কাউন্টডাউনল্যাচ কনস্ট্রাক্টরের পক্ষে কাজের সংখ্যাটি হওয়া উচিত
ChssPly76

3
আমি এই সমাধানটিকে অন্যদের তুলনায় আরও মার্জিত বলে মনে করি, মনে হয় এটি এই উদ্দেশ্যে তৈরি করা হয়েছিল, এবং এটি সহজ এবং সোজা।
wvdschel

3
আপনি যদি শুরুর আগে কাজের সংখ্যা জানেন না?
ক্লিটাস

11
@ ক্লেটাস - তারপরে আপনি একটি কাউন্টডাউনল্যাচ :-) ব্যবহার করবেন না মনে মনে, আমি এই যুক্তিটি দিচ্ছি না যে এই পদ্ধতিটি আপনার চেয়ে ভাল। যাইহোক, আমি দেখা গেছে যে বাস্তব জীবনে পরিস্থিতিতে আমি কি কাজগুলো সংখ্যা জানি, থ্রেড পুল সেটিংস না স্থাপনার প্রতি কনফিগারযোগ্য হওয়া করতে হবে, এবং পুল করতে পুনঃব্যবহার করা। সুতরাং আমার কাছে সাধারণত থ্রিং পুলগুলি স্প্রিংয়ের মাধ্যমে ইনজেকশন দেওয়া হয় এবং সেগুলি প্রোটোটাইপ হিসাবে সেট করা হয় এবং থ্রেডগুলি শেষ হওয়ার জন্য অপেক্ষা করার জন্য কেবল ম্যানুয়ালি এগুলি বন্ধ করে দেওয়া আদর্শের চেয়ে কম মনে হয়।
ChssPly76

82

ExecutorService.invokeAll() এটা তোমার জন্য করে

ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
List<Callable<?>> tasks; // your tasks
// invokeAll() returns when all tasks are complete
List<Future<?>> futures = taskExecutor.invokeAll(tasks);


@ আরগারডপ্যাক: আমি এখনও এই নির্বাহক এবং স্টাফ শিখছি। কিন্তু আপনি যা জিজ্ঞাসা করবেন তার জবাবে। একবারে 4 টি থ্রেডগুলি কি উপরের উত্তরটি ব্যবহার করে কার্যকর করা ব্যাচ টাস্কের অংশ না হওয়া উচিত?
মুকুল গোয়েল

3
আপনি যদি হাতের আগে কার্যের সংখ্যা জানেন তবে এই পদ্ধতিটি কেবলমাত্র কাজ করবে।
কনস্টান্টিন

3
আমি মনে করি যেগুলি যখন futuresফিরে আসবে, কাজগুলি শেষ হয়নি। তারা ভবিষ্যতে সম্পূর্ণ হতে পারে এবং আপনার ফলাফলের একটি লিঙ্ক থাকবে। এ কারণেই এটিকে বলা হয় Future। আপনার কাছে ফিউচার.জেট () পদ্ধতি রয়েছে , যা ফলাফল পাওয়ার জন্য টাস্কটি শেষ হওয়ার জন্য অপেক্ষা করবে।
অ্যালিকেলজিন-কিলাকা

5
জাভাডোকস থেকে @ অ্যালিক্লিজিন-কিলাকা উক্তি (উত্তরে লিঙ্কিত): "প্রদত্ত কার্যাদি কার্যকর করে ফিউচারগুলির একটি তালিকা ফিরিয়ে তাদের স্ট্যাটাস এবং ফলাফলগুলি সম্পূর্ণ হওয়ার পরে ফিরিয়ে দেয় F ফিউচার.আইসডোন () প্রত্যাবর্তিত তালিকার প্রতিটি উপাদানের জন্য সত্য। "
হাল্ক

47

আপনি ভবিষ্যতের তালিকাগুলিও ব্যবহার করতে পারেন:

List<Future> futures = new ArrayList<Future>();
// now add to it:
futures.add(executorInstance.submit(new Callable<Void>() {
  public Void call() throws IOException {
     // do something
    return null;
  }
}));

তারপরে আপনি যখন তাদের সকলের সাথে যোগ দিতে চান, এটির মূলত প্রতিটিটিতে যোগদানের সমতুল্য, (এটি অতিরিক্ত উপকারের সাথে এটি শিশু থ্রেড থেকে মূলত ব্যতিক্রমকে পুনরায় উত্থাপন করে):

for(Future f: this.futures) { f.get(); }

মূলত কৌতুকটি হ'ল প্রতিটি ভবিষ্যতে একবারে .get () কল করা হয়, অসীম লুপিং কলিংয়ের পরিবর্তে isdone () অন (সমস্ত বা প্রতিটি) কল করা হয়। সুতরাং শেষ থ্রেড শেষ হওয়ার সাথে সাথে আপনাকে এই ব্লকটি "চালিয়ে যাওয়ার" গ্যারান্টিযুক্ত। সতর্কবাণীটি হ'ল যেহেতু .get () কলটি ব্যতিক্রমগুলি পুনরায় উত্থাপন করে, যদি কোনও থ্রেড মারা যায়, অন্য থ্রেডগুলি সমাপ্ত হওয়ার আগে আপনি সম্ভবত এটি থেকে উত্থাপন করতে পারেন [এটি এড়াতে, আপনি catch ExecutionExceptionকল কলটির চারপাশে একটি যোগ করতে পারেন ]। অন্যান্য সতর্কতা হ'ল এটি সমস্ত থ্রেডের একটি রেফারেন্স রাখে যাতে তাদের থ্রেডের স্থানীয় ভেরিয়েবলগুলি থাকলে আপনি এই ব্লকটি পেরিয়ে যাওয়ার পরেও তারা সংগ্রহ করা হবে না (যদিও আপনি সমস্যাটি হয়ে উঠতে পারেন, যদি সমস্যাটি হয়ে যায় তবে অপসারণ করে ফিউচার অফ অ্যারেলিস্ট বন্ধ)। যদি আপনি জানতে চান কোন ভবিষ্যত "প্রথমে শেষ"https://stackoverflow.com/a/31885029/32453


3
কোনটি "প্রথমে শেষ" তা জানতে, ব্যবহার করুন ExecutorCompletionService.take: stackoverflow.com/a/11872604/199364
নির্মাতা

34

Java8 আপনার সাথে এটা করতে পারেন CompletableFuture :

ExecutorService es = Executors.newFixedThreadPool(4);
List<Runnable> tasks = getTasks();
CompletableFuture<?>[] futures = tasks.stream()
                               .map(task -> CompletableFuture.runAsync(task, es))
                               .toArray(CompletableFuture[]::new);
CompletableFuture.allOf(futures).join();    
es.shutdown();

3
এটি একটি খুব মার্জিত সমাধান।
mattvonb

ExecutorService es = Executors.newFixedThreadPool(4); List< Future<?>> futures = new ArrayList<>(); for(Runnable task : taskList) { futures.add(es.submit(task)); } for(Future<?> future : futures) { try { future.get(); }catch(Exception e){ // do logging and nothing else } }
ব্যবহারকারী 2862544

এসএডডাউন () এর পরে অ্যাডমস্কিওয়াকারের অপেক্ষার অবসান () দরকার?
গৌরব

@ গৌরভ আপনি যখন শাটডাউন বলবেন, কিছু কাজ এখনও শেষ নাও হতে পারে। সুতরাং অপেক্ষারত থার্মিনেশন সবকিছু শেষ না হওয়া অবধি কলিং থ্রেডটি ব্লক করে দেবে। আপনার এই থ্রেডে ফলাফলের অপেক্ষা করা দরকার কিনা তা নির্ভর করে।
অ্যাডমস্কিওয়াকার

@ অ্যাডমস্কিওয়াকার দুর্দান্ত উত্তর আমি যদি ফলাফলগুলির জন্য অপেক্ষা করতে না চাই তবে অপেক্ষা করুন () অপেক্ষারত কল করবেন না sense
গৌরব

26

শুধু আমার দুই সেন্ট। CountDownLatchআগে থেকেই কার্যগুলির সংখ্যা জানার প্রয়োজনীয়তাটি অতিক্রম করার জন্য , আপনি এটি একটি সাধারণ ব্যবহার করে পুরানো ফ্যাশন পদ্ধতিতে করতে পারেন Semaphore

ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
int numberOfTasks=0;
Semaphore s=new Semaphore(0);
while(...) {
    taskExecutor.execute(new MyTask());
    numberOfTasks++;
}

try {
    s.aquire(numberOfTasks);
...

আপনার কাজে কেবল s.release()যেমন কল করবেন তেমন কল করুনlatch.countDown();


এটি দেখে, আমি প্রথমে ভাবলাম যে যদি releaseকল হওয়ার আগে কিছু কল আসে তবে এটি সমস্যা হবে কিনা acquire, তবে সেমফোর ডকুমেন্টেশন পড়ার পরে, আমি দেখতে পাচ্ছি যে ঠিক আছে।
টুলমেকারস্টেভ

13

গেমটি থেকে কিছুটা দেরি হলেও সম্পূর্ণ হওয়ার জন্য ...

সমস্ত কাজ শেষ হওয়ার জন্য 'অপেক্ষা' করার পরিবর্তে আপনি হলিউডের নীতির শর্তে ভাবতে পারেন, "আমাকে ডাকবেন না, আমি আপনাকে ডাকব" - শেষ হয়ে গেলে। আমি মনে করি ফলাফলের কোডটি আরও মার্জিত ...

এটি সম্পাদন করার জন্য পেয়ারা কিছু আকর্ষণীয় সরঞ্জাম সরবরাহ করে।

একটি উদাহরণ ::

শ্রবণকারী এক্সেকিউটারসেবা-তে একটি এক্সিকিউটর সার্ভিস মোড়ুন ::

ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));

মৃত্যুদন্ড কার্যকর করার জন্য কলযোগ্যদের সংগ্রহ জমা দিন:

for (Callable<Integer> callable : callables) {
  ListenableFuture<Integer> lf = service.submit(callable);
  // listenableFutures is a collection
  listenableFutures.add(lf)
});

এখন প্রয়োজনীয় অংশ:

ListenableFuture<List<Integer>> lf = Futures.successfulAsList(listenableFutures);

শ্রবণযোগ্যফিউচারে একটি কলব্যাক সংযুক্ত করুন, যে সমস্ত ফিউচার সমাপ্ত হলে আপনাকে বিজ্ঞপ্তি হিসাবে ব্যবহার করতে পারেন ::

        Futures.addCallback(lf, new FutureCallback<List<Integer>>() {
        @Override
        public void onSuccess(List<Integer> result) {
            log.info("@@ finished processing {} elements", Iterables.size(result));
            // do something with all the results
        }

        @Override
        public void onFailure(Throwable t) {
            log.info("@@ failed because of :: {}", t);
        }
    });

এটি এমন সুবিধাও দেয় যে প্রসেসিং শেষ হয়ে গেলে আপনি সমস্ত ফলাফল এক জায়গায় সংগ্রহ করতে পারবেন ...

আরও তথ্য এখানে


2
খুব পরিষ্কার. এমনকি অ্যান্ড্রয়েডেও নির্বিঘ্নে কাজ করে। শুধু ব্যবহার ছিল runOnUiThread()মধ্যে onSuccess()
ডিএসচিমিট

12

CyclicBarrier জাভা 5 এবং পরে বর্গ জিনিস এই সাজানোর জন্য নির্মিত হয়েছে।


7
দুর্দান্ত, এই ডেটা কাঠামোর নামটি কখনই মনে করতে পারে না। তবে কেবলমাত্র উপযুক্ত যদি আপনি আগে থেকেই জানেন যে কতগুলি কাজ সারিবদ্ধ হবে।
16 ᆺ ᆼ

হ্যাঁ আপনি মনে করেন যে আপনি বর্তমান থ্রেড এবং সমস্ত সন্তানের থ্রেড দিয়ে বাধা মারতে সক্ষম হবেন, তারপরে আপনি যখন
এটিটি পেরেছেন

আসলে এটি ভুল উত্তর। সাইক্লিকবারিয়ার অংশগুলির জন্য ডিজাইন করা। কাউন্টডাউনল্যাচ ওয়েটিং ইভেন্টের জন্য ডিজাইন করা হয়েছে
gstackoverflow

7

নীচের পদ্ধতির একটি অনুসরণ করুন।

  1. পুনরুক্তি সব দিয়ে ভবিষ্যত কর্ম থেকে ফিরে submitউপর ExecutorServiceকল ব্লক ও স্থিতি পরীক্ষা get()উপর Futureযেমন দ্বারা প্রস্তাবিত বস্তুরKiran
  2. এক্সিকিউটর সার্ভিসে ব্যবহার invokeAll()করুন
  3. CountDownLatch
  4. ফর্কজৌইনপুল বা এক্সিকিউটার্স html # নতুন ওয়ার্কস্টিলিংপুল
  5. shutdown, awaitTermination, shutdownNowযথাযথ ক্রমে থ্রেডপুলএক্সেকিউটারের API গুলি ব্যবহার করুন

সম্পর্কিত এসই প্রশ্ন:

জাভা মাল্টিথ্রেডিংয়ে কীভাবে কাউন্টডাউনল্যাচ ব্যবহার করা হয়?

কিভাবে জাভা এক্সিকিউটর সার্ভিস সঠিকভাবে বন্ধ করবেন shut


6

এখানে দুটি বিকল্প রয়েছে, যা কিছুটা ভাল just

বিকল্প 1:

ExecutorService es = Executors.newFixedThreadPool(4);
List<Runnable> tasks = getTasks();
CompletableFuture<?>[] futures = tasks.stream()
                               .map(task -> CompletableFuture.runAsync(task, es))
                               .toArray(CompletableFuture[]::new);
CompletableFuture.allOf(futures).join();    
es.shutdown();

বিকল্প 2:

ExecutorService es = Executors.newFixedThreadPool(4);
List< Future<?>> futures = new ArrayList<>();
for(Runnable task : taskList) {
    futures.add(es.submit(task));
}

for(Future<?> future : futures) {
    try {
        future.get();
    }catch(Exception e){
        // do logging and nothing else
    }
}
es.shutdown();

এখানে ভবিষ্যত রাখা। (); চেষ্টা করে ধরা ভাল ধারণা ঠিক?


5

আপনি আপনার কাজগুলিকে অন্য চালানোতে মোড়ানো করতে পারেন, এটি বিজ্ঞপ্তি প্রেরণ করবে:

taskExecutor.execute(new Runnable() {
  public void run() {
    taskStartedNotification();
    new MyTask().run();
    taskFinishedNotification();
  }
});

1
এটি কীভাবে ওপির প্রশ্নের সমাধান করবে তা দেখার জন্য আমাকে কিছুক্ষণ সময় নিয়েছে। প্রথম, নোট করুন যে এই মোড়ানো প্রতিটি কার্যের হয়, কোডটি নয় যা সমস্ত কাজ শুরু করে। সম্ভবতঃ, প্রতিটি সূচনা একটি কাউন্টারকে বাড়িয়ে তুলত এবং প্রতিটি ফিনিসটি সেই কাউন্টারকে হ্রাস পাবে বা একটি completedপাল্টা বাড়িয়ে তুলবে । সুতরাং এগুলি সমস্ত শুরু করার পরে, প্রতিটি বিজ্ঞপ্তিতে, নির্ধারণ করতে পারে যে সমস্ত কাজ শেষ হয়েছে কিনা । মনে রাখবেন যে এটি ব্যবহার করা অত্যাবশ্যক try/finallyযাতে catchকোনও কাজ ব্যর্থ হলেও একটি সমাপ্ত বিজ্ঞপ্তি (বা ব্লকের বিকল্প বিজ্ঞপ্তি ) দেওয়া হয়। অন্যথায়, চিরকাল অপেক্ষা করা হবে।
টুলমেকারস্টেভ

3

আমি সবেমাত্র একটি নমুনা প্রোগ্রাম লিখেছি যা আপনার সমস্যার সমাধান করে। কোনও সংক্ষিপ্ত বাস্তবায়ন দেওয়া হয়নি, সুতরাং আমি এটি যুক্ত করব। আপনি যখন ব্যবহার করতে পারেন executor.shutdown()এবং executor.awaitTermination(), এটি সর্বোত্তম অনুশীলন নয় কারণ বিভিন্ন থ্রেডের দ্বারা নেওয়া সময়টি অনাকাঙ্ক্ষিত।

ExecutorService es = Executors.newCachedThreadPool();
    List<Callable<Integer>> tasks = new ArrayList<>();

    for (int j = 1; j <= 10; j++) {
        tasks.add(new Callable<Integer>() {

            @Override
            public Integer call() throws Exception {
                int sum = 0;
                System.out.println("Starting Thread "
                        + Thread.currentThread().getId());

                for (int i = 0; i < 1000000; i++) {
                    sum += i;
                }

                System.out.println("Stopping Thread "
                        + Thread.currentThread().getId());
                return sum;
            }

        });
    }

    try {
        List<Future<Integer>> futures = es.invokeAll(tasks);
        int flag = 0;

        for (Future<Integer> f : futures) {
            Integer res = f.get();
            System.out.println("Sum: " + res);
            if (!f.isDone()) 
                flag = 1;
        }

        if (flag == 0)
            System.out.println("SUCCESS");
        else
            System.out.println("FAILED");

    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }

আপনি भावी.জেটের ব্যবহার প্রদর্শন করা ভাল - এটি সম্পর্কে ভাল বিকল্প সম্পর্কে জানার জন্য। তবে আপনি কিছু সর্বাধিক গ্রহণযোগ্য সময়সীমা নির্ধারণের চেয়ে চিরকাল অপেক্ষা করা কেন ভাল মনে করেন ? আরও গুরুত্বপূর্ণ, এই যুক্তিটি করার কোনও কারণ নেই, যখন কেউ কেবলমাত্র সমস্ত কাজ শেষ না হওয়া অবধি অপেক্ষা করতে চান (মূলত চিরকালীন), অপেক্ষা করার জন্য অপেক্ষা করতে সত্যিই, সত্যিই দীর্ঘ সময় দিতে পারে।
টুলমেকারস্টেভ

এটি ইতিমধ্যে এখানে উপস্থাপিত সমাধানগুলির চেয়ে আলাদা নয়। আপনার ন্যায়সঙ্গত সমাধানটি @ sjlee
পাল্প_ ফিকশন

ওরাকল ডক অনুসারে আপনাকে কেন পরীক্ষা করতে হবে তা নিশ্চিত নন, যখন সমস্ত সম্পূর্ণ বা সময়সীমা শেষ হবে, তখন যেটি প্রথমে ঘটবে কেবলমাত্র "ইনকোকএল" ফিরে আসবে "
মাশরুর

3

ল্যাচ / প্রতিবন্ধকতাগুলি ব্যবহার করতে এখানে কেবলমাত্র আরও বিকল্প সরবরাহ করা। আপনি সমস্ত সম্পূর্ণকরণ পরিষেবা ব্যবহার না করা পর্যন্ত আপনি আংশিক ফলাফলও পেতে পারেন ।

অনুশীলনে জাভা কনকুরেন্সি থেকে: "যদি আপনার কাছে কোনও নির্বাহকের কাছে জমা দেওয়ার জন্য একটি ব্যাচ থাকে এবং আপনি তাদের ফলাফলগুলি উপলভ্য হওয়ার সাথে সাথে তা পুনরুদ্ধার করতে চান তবে আপনি প্রতিটি কাজের সাথে যুক্ত ফিউচারটি ধরে রাখতে পারেন এবং বার বার একটি উইকেটে কল করে সমাপ্তির জন্য পোল করতে পারেন শূন্য সময়সীমা। এটি সম্ভব, কিন্তু ক্লান্তিকর । ভাগ্যক্রমে আরও ভাল উপায় আছে : একটি সমাপ্তি পরিষেবা। "

এখানে বাস্তবায়ন

public class TaskSubmiter {
    private final ExecutorService executor;
    TaskSubmiter(ExecutorService executor) { this.executor = executor; }
    void doSomethingLarge(AnySourceClass source) {
        final List<InterestedResult> info = doPartialAsyncProcess(source);
        CompletionService<PartialResult> completionService = new ExecutorCompletionService<PartialResult>(executor);
        for (final InterestedResult interestedResultItem : info)
            completionService.submit(new Callable<PartialResult>() {
                public PartialResult call() {
                    return InterestedResult.doAnOperationToGetPartialResult();
                }
        });

    try {
        for (int t = 0, n = info.size(); t < n; t++) {
            Future<PartialResult> f = completionService.take();
            PartialResult PartialResult = f.get();
            processThisSegment(PartialResult);
            }
        } 
        catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } 
        catch (ExecutionException e) {
            throw somethinghrowable(e.getCause());
        }
    }
}

3

এটি "অ্যাডমস্কাইওয়ালার" টিপ-এর ভিত্তিতে আমার সমাধান and

package frss.main;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestHilos {

    void procesar() {
        ExecutorService es = Executors.newFixedThreadPool(4);
        List<Runnable> tasks = getTasks();
        CompletableFuture<?>[] futures = tasks.stream().map(task -> CompletableFuture.runAsync(task, es)).toArray(CompletableFuture[]::new);
        CompletableFuture.allOf(futures).join();
        es.shutdown();

        System.out.println("FIN DEL PROCESO DE HILOS");
    }

    private List<Runnable> getTasks() {
        List<Runnable> tasks = new ArrayList<Runnable>();

        Hilo01 task1 = new Hilo01();
        tasks.add(task1);

        Hilo02 task2 = new Hilo02();
        tasks.add(task2);
        return tasks;
    }

    private class Hilo01 extends Thread {

        @Override
        public void run() {
            System.out.println("HILO 1");
        }

    }

    private class Hilo02 extends Thread {

        @Override
        public void run() {
            try {
                sleep(2000);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("HILO 2");
        }

    }


    public static void main(String[] args) {
        TestHilos test = new TestHilos();
        test.procesar();
    }
}

2

আপনি এই কোডটি ব্যবহার করতে পারেন:

public class MyTask implements Runnable {

    private CountDownLatch countDownLatch;

    public MyTask(CountDownLatch countDownLatch {
         this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {
         try {
             //Do somethings
             //
             this.countDownLatch.countDown();//important
         } catch (InterruptedException ex) {
              Thread.currentThread().interrupt();
         }
     }
}

CountDownLatch countDownLatch = new CountDownLatch(NUMBER_OF_TASKS);
ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
for (int i = 0; i < NUMBER_OF_TASKS; i++){
     taskExecutor.execute(new MyTask(countDownLatch));
}
countDownLatch.await();
System.out.println("Finish tasks");

2

আমি নিম্নলিখিত কাজের উদাহরণ তৈরি করেছি। ধারণাটি হ'ল অনেক কাজ (একটি উদাহরণস্বরূপ একটি সারি ব্যবহার করছি) এর একটি পুল প্রক্রিয়া করার একটি উপায় আছে (নাম্বার অফটাস্ক / থ্রোসোল্ড দ্বারা প্রোগ্রামযুক্তভাবে নির্ধারিত) এবং অন্য কিছু প্রসেসিং চালিয়ে যাওয়ার জন্য সমস্ত থ্রেডগুলি সম্পন্ন না হওয়া পর্যন্ত অপেক্ষা করুন।

import java.util.PriorityQueue;
import java.util.Queue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/** Testing CountDownLatch and ExecutorService to manage scenario where
 * multiple Threads work together to complete tasks from a single
 * resource provider, so the processing can be faster. */
public class ThreadCountDown {

private CountDownLatch threadsCountdown = null;
private static Queue<Integer> tasks = new PriorityQueue<>();

public static void main(String[] args) {
    // Create a queue with "Tasks"
    int numberOfTasks = 2000;
    while(numberOfTasks-- > 0) {
        tasks.add(numberOfTasks);
    }

    // Initiate Processing of Tasks
    ThreadCountDown main = new ThreadCountDown();
    main.process(tasks);
}

/* Receiving the Tasks to process, and creating multiple Threads
* to process in parallel. */
private void process(Queue<Integer> tasks) {
    int numberOfThreads = getNumberOfThreadsRequired(tasks.size());
    threadsCountdown = new CountDownLatch(numberOfThreads);
    ExecutorService threadExecutor = Executors.newFixedThreadPool(numberOfThreads);

    //Initialize each Thread
    while(numberOfThreads-- > 0) {
        System.out.println("Initializing Thread: "+numberOfThreads);
        threadExecutor.execute(new MyThread("Thread "+numberOfThreads));
    }

    try {
        //Shutdown the Executor, so it cannot receive more Threads.
        threadExecutor.shutdown();
        threadsCountdown.await();
        System.out.println("ALL THREADS COMPLETED!");
        //continue With Some Other Process Here
    } catch (InterruptedException ex) {
        ex.printStackTrace();
    }
}

/* Determine the number of Threads to create */
private int getNumberOfThreadsRequired(int size) {
    int threshold = 100;
    int threads = size / threshold;
    if( size > (threads*threshold) ){
        threads++;
    }
    return threads;
}

/* Task Provider. All Threads will get their task from here */
private synchronized static Integer getTask(){
    return tasks.poll();
}

/* The Threads will get Tasks and process them, while still available.
* When no more tasks available, the thread will complete and reduce the threadsCountdown */
private class MyThread implements Runnable {

    private String threadName;

    protected MyThread(String threadName) {
        super();
        this.threadName = threadName;
    }

    @Override
    public void run() {
        Integer task;
        try{
            //Check in the Task pool if anything pending to process
            while( (task = getTask()) != null ){
                processTask(task);
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }finally {
            /*Reduce count when no more tasks to process. Eventually all
            Threads will end-up here, reducing the count to 0, allowing
            the flow to continue after threadsCountdown.await(); */
            threadsCountdown.countDown();
        }
    }

    private void processTask(Integer task){
        try{
            System.out.println(this.threadName+" is Working on Task: "+ task);
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }
}
}

আশা করি এটা সাহায্য করবে!


1

আপনি আপনার নিজস্ব উপশ্রেণী ব্যবহার করতে পারে ExecutorCompletionService মোড়ানো taskExecutor, এবং আপনার নিজের বাস্তবায়ন BlockingQueue অবহিত যখন প্রতিটি কাজের সম্পন্ন হয়ে পেতে এবং যাই হোক না কেন কলব্যাক বা অন্যান্য কর্ম আপনি ইচ্ছা যখন সম্পন্ন কাজগুলো নম্বর আপনার কাঙ্ক্ষিত লক্ষ্য ছুঁয়েছে সঞ্চালন।


1

আপনার ব্যবহার executorService.shutdown()এবং executorService.awaitTerminationপদ্ধতি করা উচিত ।

নিম্নলিখিত হিসাবে একটি উদাহরণ:

public class ScheduledThreadPoolExample {

    public static void main(String[] args) throws InterruptedException {
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(5);
        executorService.scheduleAtFixedRate(() -> System.out.println("process task."),
                0, 1, TimeUnit.SECONDS);

        TimeUnit.SECONDS.sleep(10);
        executorService.shutdown();
        executorService.awaitTermination(1, TimeUnit.DAYS);
    }

}

বন্ধ () /
গৌরব

1

সুতরাং আমি এখানে লিঙ্কিত প্রশ্ন থেকে আমার উত্তর পোস্ট করি, যদি কেউ এই কাজটি করার জন্য একটি সহজ উপায় চায় তবে

ExecutorService executor = Executors.newFixedThreadPool(10);
CompletableFuture[] futures = new CompletableFuture[10];
int i = 0;
while (...) {
    futures[i++] =  CompletableFuture.runAsync(runner, executor);
}

CompletableFuture.allOf(futures).join(); // THis will wait until all future ready.

0

জাভা 8 - আমরা স্ট্রিম প্রক্রিয়া করতে স্ট্রিম এপিআই ব্যবহার করতে পারি। নীচে স্নিপেট দেখুন

final List<Runnable> tasks = ...; //or any other functional interface
tasks.stream().parallel().forEach(Runnable::run) // Uses default pool

//alternatively to specify parallelism 
new ForkJoinPool(15).submit(
          () -> tasks.stream().parallel().forEach(Runnable::run) 
    ).get();

2
হাই ভ্লাদ, স্ট্যাকওভারফ্লোতে আপনাকে স্বাগতম। এটি কীভাবে প্রশ্নের উত্তর দেয় এবং কোডটি কী করে তা বোঝাতে দয়া করে আপনার উত্তরটি সম্পাদনা করতে পারেন? কোডের উত্তরগুলি এখানে নিরুৎসাহিত করা হয়। ধন্যবাদ!
টিম ম্যালোন

এই পোস্টটি সম্মতি সম্পর্কে আলোচনা করে। সমান্তরালতা! = সমঝোতা
গ্যাব্রিয়েলবিবি

0

ExecutorService WORKER_THREAD_POOL 
  = Executors.newFixedThreadPool(10);
CountDownLatch latch = new CountDownLatch(2);
for (int i = 0; i < 2; i++) {
    WORKER_THREAD_POOL.submit(() -> {
        try {
            // doSomething();
            latch.countDown();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    });
}

// wait for the latch to be decremented by the two remaining threads
latch.await();

যদি doSomething()অন্য কিছু ব্যতিক্রম নিক্ষেপ, latch.countDown(), চালানো হবে না বলে মনে হয় তাই আমি কী করা উচিত?


0

যদি আপনি যথাযথভাবে আরও বেশি থ্রেড এক্সিকিউশন সার্ভিস ব্যবহার করেন এবং প্রতিটি এক্সিকিউশন সার্ভিস সমাপ্ত হওয়ার জন্য অপেক্ষা করতে চান। সেরা উপায় নীচের মত;

ExecutorService executer1 = Executors.newFixedThreadPool(THREAD_SIZE1);
for (<loop>) {
   executer1.execute(new Runnable() {
            @Override
            public void run() {
                ...
            }
        });
} 
executer1.shutdown();

try{
   executer1.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);

   ExecutorService executer2 = Executors.newFixedThreadPool(THREAD_SIZE2);
   for (true) {
      executer2.execute(new Runnable() {
            @Override
            public void run() {
                 ...
            }
        });
   } 
   executer2.shutdown();
} catch (Exception e){
 ...
}

-1

এটি সাহায্য করতে পারে

Log.i(LOG_TAG, "shutting down executor...");
executor.shutdown();
while (true) {
                try {
                    Log.i(LOG_TAG, "Waiting for executor to terminate...");
                    if (executor.isTerminated())
                        break;
                    if (executor.awaitTermination(5000, TimeUnit.MILLISECONDS)) {
                        break;
                    }
                } catch (InterruptedException ignored) {}
            }

-1

আপনি এই রানার ক্লাসে ওয়েটটাইলডোন () কল করতে পারেন :

Runner runner = Runner.runner(4); // create pool with 4 threads in thread pool

while(...) {
    runner.run(new MyTask()); // here you submit your task
}


runner.waitTillDone(); // and this blocks until all tasks are finished (or failed)


runner.shutdown(); // once you done you can shutdown the runner

আপনি এই ক্লাসটি পুনরায় ব্যবহার করতে পারেন এবং শাটডাউন () কল করার আগে আপনি যতবার অপেক্ষা করতে পারেন ওয়েলটিলডোন () কল করতে পারেন, আপনার কোডটি চূড়ান্তভাবে সহজ । এছাড়াও আপনি জানেন করতে হবে না কাজগুলো সংখ্যা আপফ্রন্ট।

এটি ব্যবহার compile 'com.github.matejtymes:javafixes:1.3.1'করতে আপনার প্রকল্পে এই গ্রেড / খাঁটি নির্ভরতা যুক্ত করুন।

আরো বিস্তারিত এখানে পাওয়া যাবে:

https://github.com/MatejTymes/JavaFixes


-2

এক্সিকিউটারে একটি পদ্ধতি রয়েছে getActiveCount()- যা সক্রিয় থ্রেডের গণনা দেয়।

থ্রেড বিস্তৃত করার পরে, আমরা activeCount()মানটি কিনা তা পরীক্ষা করতে পারি 0। একবার মান শূন্য হয়ে গেলে, এর অর্থ বর্তমানে কোনও সক্রিয় থ্রেড চলছে না যার অর্থ টাস্ক শেষ হয়েছে:

while (true) {
    if (executor.getActiveCount() == 0) {
    //ur own piece of code
    break;
    }
}

3
নেই একটি ভাল ধারণা দেখুন stackoverflow.com/a/7271685/1166992 এবং javadoc: "। রিটার্নস থ্রেড সক্রিয়ভাবে কর্ম নির্বাহ করছে আনুমানিক সংখ্যা"
অলিভিয়ার ফাউচাক্স
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.