ভবিষ্যতের তালিকার জন্য অপেক্ষা করছি


145

আমার একটি পদ্ধতি আছে যা Listভবিষ্যতের একটি রিটার্ন দেয়

List<Future<O>> futures = getFutures();

এখন আমি অপেক্ষা করতে চাই যতক্ষণ না হয় সমস্ত ফিউচার সাফল্যের সাথে প্রক্রিয়াজাতকরণ সম্পন্ন হয় বা ভবিষ্যতে যে কোনও কাজ আউটপুট ফিরিয়ে দেয় তার ব্যতিক্রম ছোঁড়ে। এমনকি যদি কোনও কাজ ব্যতিক্রম ছুঁড়ে ফেলে তবে অন্য ফিউচারের জন্য অপেক্ষা করার কোনও মানে হয় না।

সহজ পদ্ধতির হতে হবে

wait() {

   For(Future f : futures) {
     try {
       f.get();
     } catch(Exception e) {
       //TODO catch specific exception
       // this future threw exception , means somone could not do its task
       return;
     }
   }
}

তবে এখানে সমস্যাটি হল, উদাহরণস্বরূপ, চতুর্থ ভবিষ্যত যদি একটি ব্যতিক্রম ছুঁড়ে ফেলে তবে আমি প্রথম 3 ফিউচার উপলব্ধ হওয়ার অপ্রয়োজনে অপেক্ষা করব।

কীভাবে সমাধান করবেন? কোনও উপায়ে ল্যাচ সহায়তা গণনা করবে? আমি ফিউচার ব্যবহার করতে পারছি না isDoneকারণ জাভা ডক বলেছেন

boolean isDone()
Returns true if this task completed. Completion may be due to normal termination, an exception, or cancellation -- in all of these cases, this method will return true.

1
কে এই ভবিষ্যত উত্পাদন করে? তারা কি ধরণের? ইন্টারফেস java.util.concurrent.F ভবিষ্যত আপনি যে কার্যকারিতা চান তা সরবরাহ করে না, একমাত্র উপায় হ'ল কলব্যাক সহ আপনার নিজের ফিউচার ব্যবহার করা।
আলেক্সি কাইগোরোদভ

আপনি ExecutionServiceকাজের প্রতিটি "ব্যাচ" এর উদাহরণ তৈরি করতে পারেন , সেগুলিতে এটি জমা দিন, তারপরে অবিলম্বে পরিষেবাটি বন্ধ করে দিন এবং awaitTermination()এটিতে আমি মনে করি।
মিলিমুজ

ল্যাচটিও কমেছে তা নিশ্চিত করার জন্য CountDownLatchআপনি যদি আপনার সমস্ত ফিউচারের দেহটি try..finallyজড়িয়ে রাখেন তবে আপনি এটি ব্যবহার করতে পারেন ।
মিলিমুজ

docs.oracle.com/javase/7/docs/api/java/util/concurrent/… আপনার যা প্রয়োজন ঠিক তা করে।
assylias

@AlexeiKaigorodov হ্যাঁ, আমার ভবিষ্যৎ টাইপ java.util.concurrent.I এর সাথে callable.I পেতে Futture ভবিষ্যৎ suing করছি যখন আমি একটি execureservice করার জন্য একটি টাস্ক জমা
user93796

উত্তর:


124

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

Executor executor = Executors.newFixedThreadPool(4);
CompletionService<SomeResult> completionService = 
       new ExecutorCompletionService<SomeResult>(executor);

//4 tasks
for(int i = 0; i < 4; i++) {
   completionService.submit(new Callable<SomeResult>() {
       public SomeResult call() {
           ...
           return result;
       }
   });
}

int received = 0;
boolean errors = false;

while(received < 4 && !errors) {
      Future<SomeResult> resultFuture = completionService.take(); //blocks if none available
      try {
         SomeResult result = resultFuture.get();
         received ++;
         ... // do something with the result
      }
      catch(Exception e) {
             //log
         errors = true;
      }
}

আমি মনে করি যে যদি কোনও ত্রুটি ছুড়ে দেয় তবে এখনও কার্যকর হওয়া কোনও কার্য বাতিল করতে আপনি আরও উন্নতি করতে পারবেন।


1
: আপনার কোডটিতে একই সমস্যা রয়েছে যা আমি আমার পোস্টে উল্লেখ করেছি future যদি ভবিষ্যতে ব্যতিক্রম ছুঁড়ে দেয় তবে কোডটি এখনও ভবিষ্যতের 1,2,3 সম্পূর্ণ হওয়ার জন্য অপেক্ষা করবে। বা সম্পূর্ণকরণেরেস.টেক) ভবিষ্যতটি ফিরিয়ে দেবে যা প্রথম সম্পূর্ণ হয়?
user93796

1
সময়সীমা সম্পর্কে কী? আমি কি কমপক্ষে এক্স সেকেন্ডের জন্য অপেক্ষা করতে সমাপ্তি পরিষেবাটি বলতে পারি?
ব্যবহারকারী 93796

1
হবে না. এটি ফিউচারগুলিতে পুনরাবৃত্তি হয় না, তবে এটি প্রস্তুত হওয়ার সাথে সাথেই এটি প্রসেস / যাচাই করা হয় যদি ব্যতিক্রম না ছুঁড়ে দেওয়া হয়।
dcernahoschi

2
কাতারে ভবিষ্যতের প্রত্যাশার অপেক্ষা করার জন্য সময়কালে একটি পোল (সেকেন্ড) পদ্ধতি রয়েছে CompletionService
dcernahoschi


107

আপনি যদি জাভা 8 ব্যবহার করে থাকেন তবে আপনি কমপ্লিটেবল ফিউচার এবং কমপ্লেটেবলফিউশন.অলঅফ দিয়ে এটি আরও সহজ করতে পারবেন , যা সমস্ত সরবরাহিত কমপ্লিটফিউচার সম্পন্ন হওয়ার পরে কলব্যাকটি প্রয়োগ করে।

// Waits for *all* futures to complete and returns a list of results.
// If *any* future completes exceptionally then the resulting future will also complete exceptionally.

public static <T> CompletableFuture<List<T>> all(List<CompletableFuture<T>> futures) {
    CompletableFuture[] cfs = futures.toArray(new CompletableFuture[futures.size()]);

    return CompletableFuture.allOf(cfs)
            .thenApply(ignored -> futures.stream()
                                    .map(CompletableFuture::join)
                                    .collect(Collectors.toList())
            );
}

3
হাই @ আন্ড্রেজস, আপনি কি দয়া করে ব্যাখ্যা করতে পারেন যে কোডটির এই স্নিপেটটি কী করে। আমি এটি একাধিক স্থানে প্রস্তাবিত দেখি কিন্তু আসলে কী ঘটছে তা নিয়ে বিভ্রান্ত। কোনও থ্রেড ব্যর্থ হলে ব্যতিক্রমগুলি কীভাবে পরিচালনা করা হয়?
VSEWHGHP

2
@ ভিএসইডাব্লুএইচজিএইচপি জবাডোক থেকে: প্রদত্ত কমপ্লেটেবল ফিউচার যদি কোনওরকম ব্যতিক্রমীভাবে সম্পূর্ণ হয়, তবে প্রত্যাবর্তিত কমপ্লেটেবল ফিউচারও তার ব্যতিক্রম হিসাবে এই ব্যতিক্রমটিকে ধারণ করে একটি কমপ্লিটএফসেপশন করে।
আন্দ্রেজ

1
ঠিক তাই আমি এটি অনুসরণ করে চলেছি, এই স্নিপেট ব্যবহার করে তবে অন্য সমস্ত থ্রেডের মানগুলি সাফল্যের সাথে সম্পন্ন করার কোনও উপায় আছে কি? আমি কি কেবল কমপ্লেটেবল ফিউচার তালিকার সাথে পুনরাবৃত্তি করব এবং কলটি কমপ্লেটেবল ফিউচার <তালিক <T>> এড়িয়ে যাব যেহেতু সিকোয়েন্স ফাংশনটি ফলাফল বা ব্যতিক্রমের সাথে সমস্ত থ্রেড সম্পূর্ণ হয় তা নিশ্চিত করার জন্য যত্ন নেয়?
VSEWHGHP

6
এটি একটি ভিন্ন সমস্যা সমাধান করছে। আপনার যদি Futureউদাহরণ থাকে তবে আপনি এই পদ্ধতিটি প্রয়োগ করতে পারবেন না। এটি রূপান্তর Futureকরা সহজ নয় CompletableFuture
জেরেকেকজ

আমাদের কোনও কাজে ব্যতিক্রম থাকলে তা কার্যকর হবে না।
slisnychyi

21

CompletableFutureজাভা 8 এ একটি ব্যবহার করুন

    // Kick of multiple, asynchronous lookups
    CompletableFuture<User> page1 = gitHubLookupService.findUser("Test1");
    CompletableFuture<User> page2 = gitHubLookupService.findUser("Test2");
    CompletableFuture<User> page3 = gitHubLookupService.findUser("Test3");

    // Wait until they are all done
    CompletableFuture.allOf(page1,page2,page3).join();

    logger.info("--> " + page1.get());

1
এটি গ্রহণযোগ্য উত্তর হওয়া উচিত। এছাড়াও এটি অফিশিয়াল স্প্রিং ডকুমেন্টেশনের অংশ: বসন্ত.ইউ
গুইডস

আশানুরূপ কাজ করে।
ডিমন

15

আপনি একটি এক্সিকিউটার কমপ্লিশন সার্ভিস ব্যবহার করতে পারেন । ডকুমেন্টেশনে এমনকি আপনার সঠিক ব্যবহারের ক্ষেত্রে উদাহরণ রয়েছে:

এর পরিবর্তে ধরুন যে আপনি কার্যগুলির সেটগুলির প্রথম অ-নালাম ফলাফলটি ব্যবহার করতে চান, ব্যতিক্রমগুলির মুখোমুখি হওয়া কোনও উপেক্ষা করে এবং প্রথমটি প্রস্তুত হওয়ার সাথে সাথে অন্যান্য সমস্ত কার্য বাতিল করে দিন:

void solve(Executor e, Collection<Callable<Result>> solvers) throws InterruptedException {
    CompletionService<Result> ecs = new ExecutorCompletionService<Result>(e);
    int n = solvers.size();
    List<Future<Result>> futures = new ArrayList<Future<Result>>(n);
    Result result = null;
    try {
        for (Callable<Result> s : solvers)
            futures.add(ecs.submit(s));
        for (int i = 0; i < n; ++i) {
            try {
                Result r = ecs.take().get();
                if (r != null) {
                    result = r;
                    break;
                }
            } catch (ExecutionException ignore) {
            }
        }
    } finally {
        for (Future<Result> f : futures)
            f.cancel(true);
    }

    if (result != null)
        use(result);
}

এখানে লক্ষ্য করার জন্য গুরুত্বপূর্ণ বিষয়টি হ'ল ecs.take () কেবল প্রথম জমা দেওয়া কাজ নয়, প্রথম সম্পন্ন কাজটি পাবে। সুতরাং কার্যকরভাবে শেষ (বা একটি ব্যতিক্রম নিক্ষেপ) সমাপ্তির ক্রমে আপনার এগুলি পাওয়া উচিত।


3

আপনি যদি জাভা 8 ব্যবহার করছেন এবং CompletableFutureএর কৌশলগুলি ব্যবহার করতে না চান তবে আমি একটি List<Future<T>>স্ট্রিমিং ব্যবহার করে ফলাফল পুনরুদ্ধার করার জন্য একটি সরঞ্জাম লিখেছি । মূলটি হ'ল map(Future::get)এটি নিক্ষেপ করতে আপনাকে নিষেধ করা হয়েছে ।

public final class Futures
{

    private Futures()
    {}

    public static <E> Collector<Future<E>, Collection<E>, List<E>> present()
    {
        return new FutureCollector<>();
    }

    private static class FutureCollector<T> implements Collector<Future<T>, Collection<T>, List<T>>
    {
        private final List<Throwable> exceptions = new LinkedList<>();

        @Override
        public Supplier<Collection<T>> supplier()
        {
            return LinkedList::new;
        }

        @Override
        public BiConsumer<Collection<T>, Future<T>> accumulator()
        {
            return (r, f) -> {
                try
                {
                    r.add(f.get());
                }
                catch (InterruptedException e)
                {}
                catch (ExecutionException e)
                {
                    exceptions.add(e.getCause());
                }
            };
        }

        @Override
        public BinaryOperator<Collection<T>> combiner()
        {
            return (l1, l2) -> {
                l1.addAll(l2);
                return l1;
            };
        }

        @Override
        public Function<Collection<T>, List<T>> finisher()
        {
            return l -> {

                List<T> ret = new ArrayList<>(l);
                if (!exceptions.isEmpty())
                    throw new AggregateException(exceptions, ret);

                return ret;
            };

        }

        @Override
        public Set<java.util.stream.Collector.Characteristics> characteristics()
        {
            return java.util.Collections.emptySet();
        }
    }

এটির জন্য AggregateExceptionসি # এর মতো কাজ করা দরকার

public class AggregateException extends RuntimeException
{
    /**
     *
     */
    private static final long serialVersionUID = -4477649337710077094L;

    private final List<Throwable> causes;
    private List<?> successfulElements;

    public AggregateException(List<Throwable> causes, List<?> l)
    {
        this.causes = causes;
        successfulElements = l;
    }

    public AggregateException(List<Throwable> causes)
    {
        this.causes = causes;
    }

    @Override
    public synchronized Throwable getCause()
    {
        return this;
    }

    public List<Throwable> getCauses()
    {
        return causes;
    }

    public List<?> getSuccessfulElements()
    {
        return successfulElements;
    }

    public void setSuccessfulElements(List<?> successfulElements)
    {
        this.successfulElements = successfulElements;
    }

}

এই উপাদানটি ঠিক সি # এর টাস্ক.ওয়েটএল হিসাবে ঠিক কাজ করে । আমি একটি বৈকল্পিকের সাথে কাজ করছি যা একইরকম হয় CompletableFuture.allOf(সমতুল্য Task.WhenAll)

আমি এটি করার কারণটি হ'ল আমি স্প্রিং ব্যবহার করছি ListenableFutureএবং CompletableFutureএটি একটি আরও মানসম্মত উপায় সত্ত্বেও পোর্ট করতে চাই না


1
সমমানের সমষ্টিগত ধারণার প্রয়োজনীয়তা দেখার জন্য আপভোট করুন।
গ্রানাডা কোডার

এই সুবিধা ব্যবহার করার একটি উদাহরণ চমৎকার হবে।
এক্সডিএস

1

আপনি কমপ্লেটেবল ফিউচারের একটি তালিকা একত্রিত করতে চাইলে আপনি এটি করতে পারেন:

List<CompletableFuture<Void>> futures = new ArrayList<>();
// ... Add futures to this ArrayList of CompletableFutures

// CompletableFuture.allOf() method demand a variadic arguments
// You can use this syntax to pass a List instead
CompletableFuture<Void> allFutures = CompletableFuture.allOf(
            futures.toArray(new CompletableFuture[futures.size()]));

// Wait for all individual CompletableFuture to complete
// All individual CompletableFutures are executed in parallel
allFutures.get();

ফিউচার এবং কমপ্লেটেবলফিউচার সম্পর্কিত আরও তথ্যের জন্য, দরকারী লিঙ্কগুলি:
1. ভবিষ্যত: https://www.baeldung.com/java-future
2. কমপ্লিটেবল ফিউচার : https://www.baeldung.com/java-completablefuture
3. কমপ্লেটেবলফিউচার: https : //www.callicoder.com/java-8-completablefuture-tutorial/


0

সম্ভবত এটি সাহায্য করবে (কাঁচা সুতোর সাথে কোনও কিছুই প্রতিস্থাপন হবে না, হ্যাঁ!) আমি প্রতিটি Futureলোককে পৃথক থ্রেড দিয়ে চালানোর পরামর্শ দিই (তারা সমান্তরাল হয়), তারপরে যখন কোনও ত্রুটি পেয়ে যায় তবে এটি কেবল পরিচালককে ( Handlerক্লাস) সিগন্যাল করে ।

class Handler{
//...
private Thread thisThread;
private boolean failed=false;
private Thread[] trds;
public void waitFor(){
  thisThread=Thread.currentThread();
  List<Future<Object>> futures = getFutures();
  trds=new Thread[futures.size()];
  for (int i = 0; i < trds.length; i++) {
    RunTask rt=new RunTask(futures.get(i), this);
    trds[i]=new Thread(rt);
  }
  synchronized (this) {
    for(Thread tx:trds){
      tx.start();
    }  
  }
  for(Thread tx:trds){
    try {tx.join();
    } catch (InterruptedException e) {
      System.out.println("Job failed!");break;
    }
  }if(!failed){System.out.println("Job Done");}
}

private List<Future<Object>> getFutures() {
  return null;
}

public synchronized void cancelOther(){if(failed){return;}
  failed=true;
  for(Thread tx:trds){
    tx.stop();//Deprecated but works here like a boss
  }thisThread.interrupt();
}
//...
}
class RunTask implements Runnable{
private Future f;private Handler h;
public RunTask(Future f,Handler h){this.f=f;this.h=h;}
public void run(){
try{
f.get();//beware about state of working, the stop() method throws ThreadDeath Error at any thread state (unless it blocked by some operation)
}catch(Exception e){System.out.println("Error, stopping other guys...");h.cancelOther();}
catch(Throwable t){System.out.println("Oops, some other guy has stopped working...");}
}
}

আমাকে বলতে হবে উপরের কোডটি ত্রুটি করবে (চেক হয়নি) তবে আমি আশা করি আমি সমাধানটি ব্যাখ্যা করতে পারব। দয়া করে চেষ্টা করুন


0
 /**
     * execute suppliers as future tasks then wait / join for getting results
     * @param functors a supplier(s) to execute
     * @return a list of results
     */
    private List getResultsInFuture(Supplier<?>... functors) {
        CompletableFuture[] futures = stream(functors)
                .map(CompletableFuture::supplyAsync)
                .collect(Collectors.toList())
                .toArray(new CompletableFuture[functors.length]);
        CompletableFuture.allOf(futures).join();
        return stream(futures).map(a-> {
            try {
                return a.get();
            } catch (InterruptedException | ExecutionException e) {
                //logger.error("an error occurred during runtime execution a function",e);
                return null;
            }
        }).collect(Collectors.toList());
    };

0

কমপ্লিশন সার্ভিস আপনার কলযোগ্যদের .submit () পদ্ধতির সাহায্যে গ্রহণ করবে এবং আপনি .take () পদ্ধতির সাহায্যে গণিত ফিউচারগুলি পুনরুদ্ধার করতে পারবেন।

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

উদাহরণ কোড - সমান্তরালে কাজ করার জন্য নির্দিষ্ট সংখ্যক কাজের আইটেমের জন্য:

ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

CompletionService<YourCallableImplementor> completionService = 
new ExecutorCompletionService<YourCallableImplementor>(service);

ArrayList<Future<YourCallableImplementor>> futures = new ArrayList<Future<YourCallableImplementor>>();

for (String computeMe : elementsToCompute) {
    futures.add(completionService.submit(new YourCallableImplementor(computeMe)));
}
//now retrieve the futures after computation (auto wait for it)
int received = 0;

while(received < elementsToCompute.size()) {
 Future<YourCallableImplementor> resultFuture = completionService.take(); 
 YourCallableImplementor result = resultFuture.get();
 received ++;
}
//important: shutdown your ExecutorService
service.shutdown();

উদাহরণ কোড - সমান্তরালে কাজ করার জন্য গতিশীল সংখ্যক কাজের আইটেমের জন্য:

public void runIt(){
    ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    CompletionService<CallableImplementor> completionService = new ExecutorCompletionService<CallableImplementor>(service);
    ArrayList<Future<CallableImplementor>> futures = new ArrayList<Future<CallableImplementor>>();

    //Initial workload is 8 threads
    for (int i = 0; i < 9; i++) {
        futures.add(completionService.submit(write.new CallableImplementor()));             
    }
    boolean finished = false;
    while (!finished) {
        try {
            Future<CallableImplementor> resultFuture;
            resultFuture = completionService.take();
            CallableImplementor result = resultFuture.get();
            finished = doSomethingWith(result.getResult());
            result.setResult(null);
            result = null;
            resultFuture = null;
            //After work package has been finished create new work package and add it to futures
            futures.add(completionService.submit(write.new CallableImplementor()));
        } catch (InterruptedException | ExecutionException e) {
            //handle interrupted and assert correct thread / work packet count              
        } 
    }

    //important: shutdown your ExecutorService
    service.shutdown();
}

public class CallableImplementor implements Callable{
    boolean result;

    @Override
    public CallableImplementor call() throws Exception {
        //business logic goes here
        return this;
    }

    public boolean getResult() {
        return result;
    }

    public void setResult(boolean result) {
        this.result = result;
    }
}

0

আমি একটি ইউটিলিটি ক্লাস পেয়েছি যাতে এতে রয়েছে:

@FunctionalInterface
public interface CheckedSupplier<X> {
  X get() throws Throwable;
}

public static <X> Supplier<X> uncheckedSupplier(final CheckedSupplier<X> supplier) {
    return () -> {
        try {
            return supplier.get();
        } catch (final Throwable checkedException) {
            throw new IllegalStateException(checkedException);
        }
    };
}

একবার আপনার কাছে তা হয়ে গেলে, স্ট্যাটিক আমদানি ব্যবহার করে, আপনি সহজে সমস্ত ফিউচারের জন্য অপেক্ষা করতে পারেন:

futures.stream().forEach(future -> uncheckedSupplier(future::get).get());

আপনি তাদের ফলাফলগুলি এর মতো সংগ্রহ করতে পারেন:

List<MyResultType> results = futures.stream()
    .map(future -> uncheckedSupplier(future::get).get())
    .collect(Collectors.toList());

শুধু আমার পুরানো পোস্টটি পুনর্বিবেচনা করা এবং আপনার আর একটি শোক ছিল তা লক্ষ্য করে:

তবে এখানে সমস্যাটি হল, উদাহরণস্বরূপ, চতুর্থ ভবিষ্যত যদি একটি ব্যতিক্রম ছুঁড়ে ফেলে তবে আমি প্রথম 3 ফিউচার উপলব্ধ হওয়ার অপ্রয়োজনে অপেক্ষা করব।

এই ক্ষেত্রে, সহজ সমাধানটি সমান্তরালভাবে এটি করা:

futures.stream().parallel()
 .forEach(future -> uncheckedSupplier(future::get).get());

এইভাবে প্রথম ব্যতিক্রম, যদিও এটি ভবিষ্যতে থামবে না, সিরিয়াল উদাহরণের মতো ফোর-স্টেটমেন্টটি ভেঙে দেবে, তবে যেহেতু সমস্ত সমান্তরালভাবে অপেক্ষা করে, আপনাকে প্রথম 3 টি সম্পূর্ণ হওয়ার জন্য অপেক্ষা করতে হবে না।


0
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Stack2 {   
    public static void waitFor(List<Future<?>> futures) {
        List<Future<?>> futureCopies = new ArrayList<Future<?>>(futures);//contains features for which status has not been completed
        while (!futureCopies.isEmpty()) {//worst case :all task worked without exception, then this method should wait for all tasks
            Iterator<Future<?>> futureCopiesIterator = futureCopies.iterator();
            while (futureCopiesIterator.hasNext()) {
                Future<?> future = futureCopiesIterator.next();
                if (future.isDone()) {//already done
                    futureCopiesIterator.remove();
                    try {
                        future.get();// no longer waiting
                    } catch (InterruptedException e) {
                        //ignore
                        //only happen when current Thread interrupted
                    } catch (ExecutionException e) {
                        Throwable throwable = e.getCause();// real cause of exception
                        futureCopies.forEach(f -> f.cancel(true));//cancel other tasks that not completed
                        return;
                    }
                }
            }
        }
    }
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(3);

        Runnable runnable1 = new Runnable (){
            public void run(){
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                }
            }
        };
        Runnable runnable2 = new Runnable (){
            public void run(){
                try {
                    Thread.sleep(4000);
                } catch (InterruptedException e) {
                }
            }
        };


        Runnable fail = new Runnable (){
            public void run(){
                try {
                    Thread.sleep(1000);
                    throw new RuntimeException("bla bla bla");
                } catch (InterruptedException e) {
                }
            }
        };

        List<Future<?>> futures = Stream.of(runnable1,fail,runnable2)
                .map(executorService::submit)
                .collect(Collectors.toList());

        double start = System.nanoTime();
        waitFor(futures);
        double end = (System.nanoTime()-start)/1e9;
        System.out.println(end +" seconds");

    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.