জাভা এক্সিকিউটর সার্ভিস কার্য থেকে ব্যতিক্রমগুলি হ্যান্ডেল করা


213

আমি ThreadPoolExecutorস্থির সংখ্যক থ্রেড সহ বিশাল সংখ্যক ভারী ওজন কাজ চালানোর জন্য জাভার ক্লাস ব্যবহার করার চেষ্টা করছি । প্রতিটি কার্যক্রমে অনেকগুলি স্থান রয়েছে যার সময় ব্যতিক্রমের কারণে এটি ব্যর্থ হতে পারে।

আমি সাবক্ল্যাস করেছি ThreadPoolExecutorএবং আমি সেই afterExecuteপদ্ধতিটি ওভাররাইড করে ফেলেছি যা কোনও কাজ পরিচালনার সময় সম্মুখীন হওয়া কোনও অনিচ্ছাকৃত ব্যতিক্রম সরবরাহ করার কথা। যাইহোক, আমি এটি কাজ করে বলে মনে হচ্ছে না।

উদাহরণ স্বরূপ:

public class ThreadPoolErrors extends ThreadPoolExecutor {
    public ThreadPoolErrors() {
        super(  1, // core threads
                1, // max threads
                1, // timeout
                TimeUnit.MINUTES, // timeout units
                new LinkedBlockingQueue<Runnable>() // work queue
        );
    }

    protected void afterExecute(Runnable r, Throwable t) {
        super.afterExecute(r, t);
        if(t != null) {
            System.out.println("Got an error: " + t);
        } else {
            System.out.println("Everything's fine--situation normal!");
        }
    }

    public static void main( String [] args) {
        ThreadPoolErrors threadPool = new ThreadPoolErrors();
        threadPool.submit( 
                new Runnable() {
                    public void run() {
                        throw new RuntimeException("Ouch! Got an error.");
                    }
                }
        );
        threadPool.shutdown();
    }
}

এই প্রোগ্রামটির আউটপুটটি "সবকিছু ঠিক আছে - পরিস্থিতি স্বাভাবিক!" যদিও থ্রেড পুলে জমা হওয়া একমাত্র রান্নেবল ব্যতিক্রম ছুঁড়ে। এখানে কি চলছে তার কোনও ক্লু?

ধন্যবাদ!


আপনি কখনই কাজের ভবিষ্যত সম্পর্কে জিজ্ঞাসা করেননি, সেখানে কী ঘটেছিল। পুরো পরিষেবা নির্বাহক বা প্রোগ্রাম ক্র্যাশ হতে চলেছে না। ব্যতিক্রমটি ক্যাচ করা হয়েছে এবং এক্সিকিউশনএক্সসেপশন এর আওতায় রয়েছে। আপনি যদি ভবিষ্যতকে কল করেন তবে সে পুনর্বিবেচনা করবে get পিএস: ভবিষ্যত.আইসোন () [দয়া করে আসল এপিআই নামটি পড়ুন] সত্য ফিরে আসবে, এমনকি যখন রান রানযোগ্যভাবে ভুলভাবে শেষ হয়েছে। কারণ কাজটি বাস্তবের জন্য সম্পন্ন হয়েছে।
জয় পণ্ডিত

উত্তর:


156

দস্তাবেজগুলি থেকে :

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

আপনি যখন রান রানযোগ্য জমা দেবেন, এটি ভবিষ্যতে আবৃত হবে।

আপনার পরের এক্সেক্টটি এমন কিছু হওয়া উচিত:

public final class ExtendedExecutor extends ThreadPoolExecutor {

    // ...

    protected void afterExecute(Runnable r, Throwable t) {
        super.afterExecute(r, t);
        if (t == null && r instanceof Future<?>) {
            try {
                Future<?> future = (Future<?>) r;
                if (future.isDone()) {
                    future.get();
                }
            } catch (CancellationException ce) {
                t = ce;
            } catch (ExecutionException ee) {
                t = ee.getCause();
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt();
            }
        }
        if (t != null) {
            System.out.println(t);
        }
    }
}

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

1
এক্সিকিউটারকে সাবক্লাসিং করার আরেকটি পন্থা হ'ল ফিউচারটাস্ক সাবক্লাস করা এবং তার 'সম্পন্ন' পদ্ধতিটি ওভাররাইড করা
নং

1
টম >> আপনি দয়া করে আপনার নমুনা স্নিপেট কোড পোস্ট করতে পারেন যেখানে আপনি
কার্যনির্বাহক পরিষেবাটি

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

2
ভবিষ্যতের ব্যবহার শেষ হয়ে গেছে কিনা তা কি আমাদের যাচাই করতে হবে future.isDone()? যেহেতু সম্পন্ন afterExecuteহওয়ার পরে চালানো Runnableহয়, তাই আমি ধরে নিই future.isDone()সবসময় ফিরবে true
সাগরেন

248

সতর্কতা : এটি দ্রষ্টব্য যে এই সমাধান কলিং থ্রেড ব্লক করবে।


আপনি যদি টাস্কটি ফেলে দেওয়া ব্যতিক্রমগুলি প্রক্রিয়া করতে চান তবে সাধারণত এটির Callableপরিবর্তে ব্যবহার করা ভালRunnable

Callable.call() চেক করা ব্যতিক্রম নিক্ষেপ করার অনুমতি দেওয়া হয় এবং সেগুলি কলিং থ্রেডে ফিরে প্রচারিত হয়:

Callable task = ...
Future future = executor.submit(task);
try {
   future.get();
} catch (ExecutionException ex) {
   ex.getCause().printStackTrace();
}

যদি Callable.call()একটি ব্যতিক্রম ছোঁড়ার, এই একটি আবৃত করা হবে না ExecutionExceptionএবং দ্বারা নিক্ষিপ্ত Future.get()

এটি সাবক্লাসিংয়ের চেয়ে অনেক বেশি পছন্দনীয় ThreadPoolExecutor। এটি ব্যতিক্রম পুনরুদ্ধারযোগ্য যদি হয় তবে আপনাকে টাস্কটি পুনরায় জমা দেওয়ার সুযোগ দেয়।


5
> Callable.call () চেক করা ব্যতিক্রম ছুঁড়ে ফেলার অনুমতি দেওয়া হয়েছে এবং এগুলি কলিং থ্রেডে ফিরে প্রচারিত হয়েছে: নোট করুন যে নিক্ষিপ্ত ব্যতিক্রম কলিং থ্রেডে কেবল তখন প্রচার করা হবে future.get()বা তার ওভারলোডেড সংস্করণটি বলা হয়ে থাকে।

16
এটি নিখুঁত, তবে যদি আমি সমান্তরালভাবে কাজগুলি চালনা করি এবং সম্পাদন অবরুদ্ধ করতে না চান তবে কী করব?
গ্রেগরি কিসলিন

43
এই সমাধানটি ব্যবহার করবেন না, কারণ এটি এক্সিকিউটর সার্ভিস ব্যবহারের পুরো উদ্দেশ্যটি ভঙ্গ করে। একটি এক্সিকিউটর সার্ভিস একটি অ্যাসিক্রোনাস এক্সিকিউশন মেকানিজম যা ব্যাকগ্রাউন্ডে কার্য সম্পাদন করতে সক্ষম। যদি আপনি ডিউটিউইচ করার ঠিক পরে ভবিষ্যতে।
ব্যবহারকারী1801374

2
এই সমাধানটি এত বেশি রেট দেওয়া উচিত নয়। ফিউচার.জেট () সমকালীনভাবে কাজ করে এবং চালানো বা কলযোগ্য কার্যকর না হওয়া পর্যন্ত এবং ব্লক হিসাবে কাজ করবে এবং উপরে বর্ণিত হিসাবে এক্সিকিউটর পরিষেবাটি ব্যবহারের উদ্দেশ্যকে হারাবে
সুপার হ্যান্স

2
# অলঙ্কৃত হিসাবে উল্লেখ করা হয়েছে, এটি একটি জেডিকে বিইউজি প্রাপ্য। যদি ফিউচার.জেট () না ডাকা হয়, কলযোগ্য থেকে প্রাপ্ত কোনও অপ্রয়োজনীয় চুপচাপ উপেক্ষা করা হবে। খুব খারাপ ডিজাইন .... একটি লাইব্রেরি এটি ব্যবহৃত হয়েছে তা বের করতে সবে মাত্র 1+ দিন ব্যয় করেছে এবং jdk নীরবে ব্যতিক্রম উপেক্ষা করেছে। এবং, এটি এখনও jdk12 এ বিদ্যমান।
বেন জিয়াং

18

এই আচরণের ব্যাখ্যাটি এক্সকিউটের পরে জাভাদকে সঠিক :

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


10

এক্সিকিউটারের কাছে সরবরাহ করা রান্নেবল মোড়ক করে আমি এটির কাছাকাছি পৌঁছে গেলাম।

CompletableFuture.runAsync(() -> {
        try {
              runnable.run();
        } catch (Throwable e) {
              Log.info(Concurrency.class, "runAsync", e);
        }
}, executorService);

3
আপনি whenComplete()পদ্ধতি ব্যবহার করে পাঠযোগ্যতার উন্নতি করতে পারেন CompletableFuture
এডুয়ার্ড ভার্চ

@ এডওয়ার্ড ভার্চ এটি কাজ করে তবে আপনি যখন আপত্তি () থেকে ব্যতিক্রম করতে পারবেন না
অক্ষত

7

আমি জেসিবি-লগVerboseRunnable থেকে ক্লাস ব্যবহার করছি , যা সমস্ত ব্যতিক্রম গ্রাস করে এবং সেগুলি লগ করে। খুব সুবিধাজনক, উদাহরণস্বরূপ:

import com.jcabi.log.VerboseRunnable;
scheduler.scheduleWithFixedDelay(
  new VerboseRunnable(
    Runnable() {
      public void run() { 
        // the code, which may throw
      }
    },
    true // it means that all exceptions will be swallowed and logged
  ),
  1, 1, TimeUnit.MILLISECONDS
);

3

আর একটি সমাধান হ'ল ম্যানেজডটাস্ক এবং ম্যানেজডটাস্কলিস্টনার ব্যবহার ।

আপনার একটি কলযোগ্য বা চলমান দরকার যা ইন্টারফেস ম্যানেজডটাস্ক প্রয়োগ করে ।

পদ্ধতি getManagedTaskListener পছন্দসই উদাহরণটি দেয়।

public ManagedTaskListener getManagedTaskListener() {

আর তুমি বাস্তবায়ন ManagedTaskListenertaskDone পদ্ধতি:

@Override
public void taskDone(Future<?> future, ManagedExecutorService executor, Object task, Throwable exception) {
    if (exception != null) {
        LOGGER.log(Level.SEVERE, exception.getMessage());
    }
}

পরিচালিত টাস্ক লাইফসাইকেল এবং শ্রোতা সম্পর্কে আরও বিশদ ।


2

এইটা কাজ করে

  • এটি সিঙ্গলথ্রেডএক্সেক্টর থেকে উদ্ভূত, তবে আপনি এটি সহজেই মানিয়ে নিতে পারেন
  • জাভা 8 লামডাস কোড, তবে ঠিক করা সহজ

এটি একটি একক থ্রেড দিয়ে একটি নির্বাহক তৈরি করবে, যা অনেকগুলি কার্য পেতে পারে; এবং বর্তমানের পরবর্তীটির সাথে শুরু হয়ে মৃত্যুদন্ড কার্যকর হওয়ার অপেক্ষায় থাকবে

Uncaugth ত্রুটি বা ব্যতিক্রম ক্ষেত্রে uncaughtExceptionHandler এটা ফেলবো

পাবলিক ফাইনাল ক্লাস সিঙ্গলথ্রেডএ্যাকসিকিউটরও এক্সেক্সশনস ith

    পাবলিক স্ট্যাটিক এক্সিকিউটরসিভাসি নিউসিংলথ্র্যাডএ্যাকসিকিউটর উইথ এক্সেপশনস (চূড়ান্ত থ্রেড .উনাকুটেএক্সেপশনহ্যান্ডলার অচেতন এক্সেকশনহ্যান্ডলার) {

        থ্রেডফ্যাক্টরি কারখানা = (চলমান চলমান) -> {
            চূড়ান্ত থ্রেড newThread = নতুন থ্রেড (চলমান, "SingleThreadExecutorWithExferences");
            newThread.setUncaughtExceptionHandler ((চূড়ান্ত থ্রেড কৌগথথ্রেড, চূড়ান্ত থ্রোয়েবল থ্রোয়েবল))> {
                uncaughtExceptionHandler.uncaughtException (কৌগথথ্রেড, থ্রোয়েবল);
            });
            newThread ফিরুন;
        };
        নতুন FinalizableDelegatedExecutorService ফিরিয়ে দিন
                (নতুন থ্রেডপুলএক্সিকিউটর (1, 1,
                        0 এল, টাইমউনিট
                        নতুন লিঙ্কডব্লকিংকিউ (),
                        কারখানা) {


                    এক্সেক্টের পর অকার্যকর সুরক্ষিত (চলমান চলমান, থ্রোয়েবল থ্রোয়েবল) {
                        super. afterExecute (চলমান, নিক্ষেপযোগ্য);
                        যদি (নিক্ষিপ্ত == নাল && ভবিষ্যতে চালানোযোগ্য উদাহরণ) {
                            চেষ্টা করুন
                                ভবিষ্যত ভবিষ্যত = (ভবিষ্যত) রান্নেবল;
                                যদি (ভবিষ্যত.ইসডোন ())
                                    future.get ();
                                }
                            } ধরা (বাতিলকরণ এক্সসেপশন সিই) {
                                নিক্ষেপযোগ্য = ce;
                            } ধরা (এক্সিকিউশনএক্সেপশন ই) {
                                নিক্ষেপযোগ্য = ee.getCause ();
                            } ধরা (বাধাপ্রাপ্তি গ্রহণ) অর্থাৎ)
                                Thread.currentThread () বিঘ্ন ()। // উপেক্ষা / পুনরায় সেট করুন
                            }
                        }
                        যদি (নিক্ষেপযোগ্য! = নাল) {
                            uncaughtExceptionHandler.uncaughtException (Thread.currentThread (), নিক্ষেপযোগ্য);
                        }
                    }
                });
    }



    বেসরকারী স্ট্যাটিক শ্রেণি চূড়ান্তকরণযোগ্য ডেলিগেটেড এক্সেকিউটারসেবা
            ডেলিগেটেড এক্সেকিউটারসেবা extend
        FinalizableDelegatedExecutorService (এক্সিকিউটারসেবা এক্সিকিউটর) {
            সুপার (নির্বাহক);
        }
        সুরক্ষিত অকার্যকর চূড়ান্তকরণ () {
            super.shutdown ();
        }
    }

    / **
     * একটি মোড়কের ক্লাস যা কেবলমাত্র এক্সিকিউটর সার্ভিস পদ্ধতিগুলি প্রকাশ করে
     একটি এক্সিকিউটারসেবা বাস্তবায়ন *।
     * /
    প্রাইভেট স্ট্যাটিক ক্লাস ডেলিগেটেড এক্সেকিউটারসেবা বিস্তৃত অ্যাবস্ট্রাক্ট এক্সেকিউটারসেবা {
        বেসরকারী চূড়ান্ত নির্বাহক পরিষেবা ই;
        ডেলিগেটেডএকসিকিউটর সার্ভিস (এক্সিকিউটর সার্ভিস এক্সিকিউটার) {ই = এক্সিকিউটর; }
        সর্বজনীন শূন্য এক্সিকিউট (রান্নেবল কমান্ড)। e.execute (কমান্ড); }
        সর্বজনীন শূন্যতম শাটডাউন ()। ই.শুটডাউন (); }
        সর্বজনীন তালিকা শাটডাউন এখন () {রিটার্ন e.shutdownNow (); }
        পাবলিক বুলিয়ান শটডাউন () {রিটার্ন e.isSututdown (); }
        পাবলিক বুলিয়ান isTerminated () {রিটার্ন e.isTerminated (); }
        পাবলিক বুলিয়ান অপেক্ষার সমাপ্তি (দীর্ঘ সময়সীমা, টাইমউনিট ইউনিট)
                বিঘ্নিত ধারণাটি ছুড়ে ফেলে {
            রিটার্ন e.awaitTerination (সময়সীমা, ইউনিট);
        }
        সর্বজনীন ভবিষ্যতের জমা (চলমান টাস্ক) {
            রিটার্ন e.submit (টাস্ক);
        }
        পাবলিক ফিউচার জমা (কলযোগ্য টাস্ক) {
            রিটার্ন e.submit (টাস্ক);
        }
        সর্বজনীন ভবিষ্যত জমা দিন (চলমান টাস্ক, টি ফলাফল) {
            রিটার্ন e.submit (কার্য, ফলাফল);
        }
        সর্বজনীন তালিকা> ইনভোকএল (সংগ্রহ> কার্য)
                বিঘ্নিত ধারণাটি ছুড়ে ফেলে {
            e.invokeAll (কার্য) রিটার্ন করুন;
        }
        সর্বজনীন তালিকা> ইনভোকএল (সংগ্রহ) কার্যগুলি,
                                             দীর্ঘ সময়সীমা, টাইমউনিট ইউনিট)
                বিঘ্নিত ধারণাটি ছুড়ে ফেলে {
            e.invokeAll (কর্ম, সময়সীমা, ইউনিট) রিটার্ন করুন;
        }
        সর্বজনীন টি দাওয়াত করুন (সংগ্রহ> কার্য)
                বিঘ্নিত এক্সসেপশন, এক্সিকিউশনএক্সেপশন th
            e.invokeAny (কর্ম) রিটার্ন করুন;
        }
        সর্বজনীন টি আহ্বান করুন (সংগ্রহ> কার্যগুলি,
                               দীর্ঘ সময়সীমা, টাইমউনিট ইউনিট)
                বিঘ্নিত এক্সসেপশন, এক্সিকিউশন এক্সেপশন, টাইমআউট এক্সেপশন th
            e.invokeAny রিটার্ন করুন (টাস্কস, সময়সীমা, ইউনিট);
        }
    }



    প্রাইভেট সিঙ্গলথ্রেডএক্সিকিউটর এক্সেক্সসেপস () এর সাথে)}
}

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

1

আপনি যদি কার্য সম্পাদন নিরীক্ষণ করতে চান তবে আপনি 1 বা 2 থ্রেড স্পিন করতে পারেন (সম্ভবত লোডের উপর নির্ভর করে আরও) এবং একটি এক্সিকিউশন কমপ্লিশন সার্ভিস র‌্যাপার থেকে কাজগুলি নিতে তাদের ব্যবহার করতে পারেন।


0

যদি আপনার ExecutorServiceকোনও বাহ্যিক উত্স থেকে আসে (যেমন সাবক্লাস ThreadPoolExecutorএবং ওভাররাইড করা সম্ভব নয় afterExecute()), আপনি পছন্দসই আচরণ অর্জনের জন্য ডায়নামিক প্রক্সি ব্যবহার করতে পারেন:

public static ExecutorService errorAware(final ExecutorService executor) {
    return (ExecutorService) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
            new Class[] {ExecutorService.class},
            (proxy, method, args) -> {
                if (method.getName().equals("submit")) {
                    final Object arg0 = args[0];
                    if (arg0 instanceof Runnable) {
                        args[0] = new Runnable() {
                            @Override
                            public void run() {
                                final Runnable task = (Runnable) arg0;
                                try {
                                    task.run();
                                    if (task instanceof Future<?>) {
                                        final Future<?> future = (Future<?>) task;

                                        if (future.isDone()) {
                                            try {
                                                future.get();
                                            } catch (final CancellationException ce) {
                                                // Your error-handling code here
                                                ce.printStackTrace();
                                            } catch (final ExecutionException ee) {
                                                // Your error-handling code here
                                                ee.getCause().printStackTrace();
                                            } catch (final InterruptedException ie) {
                                                Thread.currentThread().interrupt();
                                            }
                                        }
                                    }
                                } catch (final RuntimeException re) {
                                    // Your error-handling code here
                                    re.printStackTrace();
                                    throw re;
                                } catch (final Error e) {
                                    // Your error-handling code here
                                    e.printStackTrace();
                                    throw e;
                                }
                            }
                        };
                    } else if (arg0 instanceof Callable<?>) {
                        args[0] = new Callable<Object>() {
                            @Override
                            public Object call() throws Exception {
                                final Callable<?> task = (Callable<?>) arg0;
                                try {
                                    return task.call();
                                } catch (final Exception e) {
                                    // Your error-handling code here
                                    e.printStackTrace();
                                    throw e;
                                } catch (final Error e) {
                                    // Your error-handling code here
                                    e.printStackTrace();
                                    throw e;
                                }
                            }
                        };
                    }
                }
                return method.invoke(executor, args);
            });
}

0

এই কারণে হয় AbstractExecutorService :: submitআপনার মোড়কে হয় runnableমধ্যে RunnableFuture(কিছুই কিন্তু FutureTaskনিচে মত)

AbstractExecutorService.java

public Future<?> submit(Runnable task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<Void> ftask = newTaskFor(task, null); /////////HERE////////
    execute(ftask);
    return ftask;
}

তারপরে executeএটি পাস করবে Workerএবং Worker.run()নীচে কল করবে।

ThreadPoolExecutor.java

final void runWorker(Worker w) {
    Thread wt = Thread.currentThread();
    Runnable task = w.firstTask;
    w.firstTask = null;
    w.unlock(); // allow interrupts
    boolean completedAbruptly = true;
    try {
        while (task != null || (task = getTask()) != null) {
            w.lock();
            // If pool is stopping, ensure thread is interrupted;
            // if not, ensure thread is not interrupted.  This
            // requires a recheck in second case to deal with
            // shutdownNow race while clearing interrupt
            if ((runStateAtLeast(ctl.get(), STOP) ||
                 (Thread.interrupted() &&
                  runStateAtLeast(ctl.get(), STOP))) &&
                !wt.isInterrupted())
                wt.interrupt();
            try {
                beforeExecute(wt, task);
                Throwable thrown = null;
                try {
                    task.run();           /////////HERE////////
                } catch (RuntimeException x) {
                    thrown = x; throw x;
                } catch (Error x) {
                    thrown = x; throw x;
                } catch (Throwable x) {
                    thrown = x; throw new Error(x);
                } finally {
                    afterExecute(task, thrown);
                }
            } finally {
                task = null;
                w.completedTasks++;
                w.unlock();
            }
        }
        completedAbruptly = false;
    } finally {
        processWorkerExit(w, completedAbruptly);
    }
}

শেষ task.run();পর্যন্ত উপরের কোড কল কল করবে FutureTask.run()। এখানে ব্যতিক্রম হ্যান্ডলার কোডটি রয়েছে, এর কারণে আপনি প্রত্যাশিত ব্যতিক্রমটি পাচ্ছেন না।

class FutureTask<V> implements RunnableFuture<V>

public void run() {
    if (state != NEW ||
        !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                     null, Thread.currentThread()))
        return;
    try {
        Callable<V> c = callable;
        if (c != null && state == NEW) {
            V result;
            boolean ran;
            try {
                result = c.call();
                ran = true;
            } catch (Throwable ex) {   /////////HERE////////
                result = null;
                ran = false;
                setException(ex);
            }
            if (ran)
                set(result);
        }
    } finally {
        // runner must be non-null until state is settled to
        // prevent concurrent calls to run()
        runner = null;
        // state must be re-read after nulling runner to prevent
        // leaked interrupts
        int s = state;
        if (s >= INTERRUPTING)
            handlePossibleCancellationInterrupt(s);
    }
}

0

এটি মিমি এর সমাধানের মতো, তবে এটি আরও কিছুটা বোধগম্য। আপনার কাজগুলিকে একটি বিমূর্ত শ্রেণি প্রসারিত করুন যা রান () পদ্ধতিটি মোড়বে।

public abstract Task implements Runnable {

    public abstract void execute();

    public void run() {
      try {
        execute();
      } catch (Throwable t) {
        // handle it  
      }
    }
}


public MySampleTask extends Task {
    public void execute() {
        // heavy, error-prone code here
    }
}

-4

থ্রেডপুলএক্সেকিউটারকে সাবক্লাসিংয়ের পরিবর্তে, আমি এটিকে একটি থ্রেডফ্যাক্টরি উদাহরণ সরবরাহ করব যা নতুন থ্রেড তৈরি করে এবং তাদেরকে একটি অবিস্মরণীয় এক্সপ্লেশনহ্যান্ডলার সরবরাহ করে


3
আমি এটিও চেষ্টা করে দেখেছি, তবে অনুমিত ধারণা পদ্ধতিটি কখনও কল হতে পারে বলে মনে হয় না। আমি বিশ্বাস করি এটি হ'ল কারণ থ্রেডপুলএক্সেক্টর শ্রেণিতে কোনও শ্রমিক থ্রেড ব্যতিক্রমগুলি ধরছে।
টম

5
অ্যাক্সড এক্সসেপশন পদ্ধতিটি বলা হয় না কারণ এক্সিকিউটর সার্ভিসের জমা দেওয়ার পদ্ধতিটি ভবিষ্যতে কলযোগ্য / চলমানযোগ্য মোড়ানো হয়; ব্যতিক্রম সেখানে ধরা হচ্ছে।
এমিল সিট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.