এক্সিকিউটর সার্ভিস যা একটি সময় শেষ হওয়ার পরে কার্যগুলিতে বাধা দেয়


95

আমি একটি এক্সিকিউটর সার্ভিস বাস্তবায়ন খুঁজছি যা একটি সময়সীমা সহ সরবরাহ করা যায়। এক্সিকিউটর সার্ভিসে জমা দেওয়া টাস্কগুলি সঞ্চালনের সময়সীমা চেয়ে বেশি সময় নিলে বাধা দেওয়া হয়। এ জাতীয় জন্তুটি কার্যকর করা এত কঠিন কাজ নয়, তবে আমি ভাবছি যে বিদ্যমান বাস্তবায়ন সম্পর্কে কেউ জানেন কিনা।

নীচে কিছু আলোচনার ভিত্তিতে আমি কী নিয়ে এলাম তা এখানে। কোন মন্তব্য?

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

public class TimeoutThreadPoolExecutor extends ThreadPoolExecutor {
    private final long timeout;
    private final TimeUnit timeoutUnit;

    private final ScheduledExecutorService timeoutExecutor = Executors.newSingleThreadScheduledExecutor();
    private final ConcurrentMap<Runnable, ScheduledFuture> runningTasks = new ConcurrentHashMap<Runnable, ScheduledFuture>();

    public TimeoutThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, long timeout, TimeUnit timeoutUnit) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
        this.timeout = timeout;
        this.timeoutUnit = timeoutUnit;
    }

    public TimeoutThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, long timeout, TimeUnit timeoutUnit) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
        this.timeout = timeout;
        this.timeoutUnit = timeoutUnit;
    }

    public TimeoutThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler, long timeout, TimeUnit timeoutUnit) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
        this.timeout = timeout;
        this.timeoutUnit = timeoutUnit;
    }

    public TimeoutThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler, long timeout, TimeUnit timeoutUnit) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
        this.timeout = timeout;
        this.timeoutUnit = timeoutUnit;
    }

    @Override
    public void shutdown() {
        timeoutExecutor.shutdown();
        super.shutdown();
    }

    @Override
    public List<Runnable> shutdownNow() {
        timeoutExecutor.shutdownNow();
        return super.shutdownNow();
    }

    @Override
    protected void beforeExecute(Thread t, Runnable r) {
        if(timeout > 0) {
            final ScheduledFuture<?> scheduled = timeoutExecutor.schedule(new TimeoutTask(t), timeout, timeoutUnit);
            runningTasks.put(r, scheduled);
        }
    }

    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        ScheduledFuture timeoutTask = runningTasks.remove(r);
        if(timeoutTask != null) {
            timeoutTask.cancel(false);
        }
    }

    class TimeoutTask implements Runnable {
        private final Thread thread;

        public TimeoutTask(Thread thread) {
            this.thread = thread;
        }

        @Override
        public void run() {
            thread.interrupt();
        }
    }
}

সময়সীমাটির 'স্টার্ট টাইম' কি জমা দেওয়ার সময়? বা সময়টি কার্যকর করার সময় শুরু হয়?
টিম বেন্ডার

ভাল প্রশ্ন. এটি কার্যকর করা শুরু হয়। সম্ভবত protected void beforeExecute(Thread t, Runnable r)হুক ব্যবহার করা ।
এডওয়ার্ড ডেল

@ scompt.com আপনি কি এখনও এই সমাধানটি ব্যবহার করছেন বা এটি সুপারসাইড করা হয়েছে
পল টেলর

@ পল টায়লর যেখানে আমি এই সমাধানটি প্রয়োগ করেছি সেখানে কার্যকর হয়েছে। :-)
এডওয়ার্ড ডেল

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

উত্তর:


91

আপনি এটির জন্য একটি শিডিউডএক্সেক্টর সার্ভিস ব্যবহার করতে পারেন । প্রথমে আপনি তাৎক্ষণিকভাবে শুরু হওয়ার জন্য এবং ভবিষ্যতের তৈরি ভবিষ্যতটি ধরে রাখতে কেবল একবার এটি জমা দেবেন। এর পরে আপনি একটি নতুন কার্য জমা দিতে পারেন যা কিছু সময়ের পরে ধরে রাখা ভবিষ্যত বাতিল করে দেয়।

 ScheduledExecutorService executor = Executors.newScheduledThreadPool(2); 
 final Future handler = executor.submit(new Callable(){ ... });
 executor.schedule(new Runnable(){
     public void run(){
         handler.cancel();
     }      
 }, 10000, TimeUnit.MILLISECONDS);

এটি 10 ​​সেকেন্ডের জন্য আপনার হ্যান্ডলারের (বাধা দেওয়ার মূল কার্যকারিতা) কার্যকর করবে, তারপরে সেই নির্দিষ্ট কাজটি বাতিল করবে (অর্থাত্‍ বাধা দেওয়া)।


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

4
নির্বাহক কেবল একবার এই বাতিল করার সময়সূচি দেবেন। যদি টাস্কটি সম্পন্ন হয় তবে বাতিলটি কোনও বিকল্প নয় এবং কাজটি অপরিবর্তিত রয়েছে। কাজগুলি বাতিল করতে কেবল একটি অতিরিক্ত থ্রেড স্কুডলিং থাকা প্রয়োজন এবং সেগুলি চালানোর জন্য একটি থ্রেড রয়েছে। আপনার দু'জন এক্সিকিউটার থাকতে পারে, একজন আপনার মূল কাজগুলি জমা দেওয়ার জন্য এবং একটি তাদের বাতিল করার জন্য।
জন ভিন্ট

4
এটি সত্য, তবে কী যদি সময়সীমা 5 ঘন্টা হয় এবং সেই সময়ে 10 কে কাজ সম্পাদিত হয়। আমি এই সমস্ত নো-অপসকে স্মৃতি গ্রহণ এবং প্রসঙ্গের স্যুইচগুলি ঘটাতে এড়াতে চাই।
এডওয়ার্ড ডেল

4
@ এসকম্প্ট অগত্যা নয়। সেখানে 10 ক ভবিষ্যতের কনসাল () অনুরোধ থাকবে, তবে যদি ভবিষ্যতটি শেষ হয়ে যায় তবে বাতিলটি দ্রুত পথ পাবে এবং কোনও অনিচ্ছাকৃত কাজ করবে না। আপনি যদি 10 কে অতিরিক্ত বাতিলের অনুরোধ না চান তবে এটি কাজ নাও করতে পারে, তবে কোনও কাজ শেষ হলে কাজ করার পরিমাণ খুব কম is
জন ভিন্ট

6
@ জন ডাব্লু .: আপনার প্রয়োগের সাথে আমি আরও একটি সমস্যা বুঝতে পেরেছি। আমি আগে মন্তব্য হিসাবে যেমন টাস্ক কার্যকর করা শুরু হবে তখন আমার সময়সীমা শুরু হওয়া দরকার। আমি মনে করি এটি করার একমাত্র উপায় beforeExecuteহুক ব্যবহার করা ।
এডওয়ার্ড ডেল 16

6

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

অতএব যদি আপনি TimeoutThreadPoolExecutorমোটামুটি দীর্ঘ মেয়াদোত্তীর্ণ সময় (একটি সাধারণ ব্যবহার) দিয়ে একটি তৈরি করেন এবং দ্রুত কার্যগুলি জমা দেন তবে আপনি মেমরিটি পূরণ করবেন - যদিও কার্যগুলি সফলভাবে সফলভাবে শেষ হয়েছে।

আপনি নিম্নলিখিত (খুব অশোধিত) পরীক্ষা প্রোগ্রামের সাথে সমস্যাটি দেখতে পারেন:

public static void main(String[] args) throws InterruptedException {
    ExecutorService service = new TimeoutThreadPoolExecutor(1, 1, 10, TimeUnit.SECONDS, 
            new LinkedBlockingQueue<Runnable>(), 10, TimeUnit.MINUTES);
    //ExecutorService service = Executors.newFixedThreadPool(1);
    try {
        final AtomicInteger counter = new AtomicInteger();
        for (long i = 0; i < 10000000; i++) {
            service.submit(new Runnable() {
                @Override
                public void run() {
                    counter.incrementAndGet();
                }
            });
            if (i % 10000 == 0) {
                System.out.println(i + "/" + counter.get());
                while (i > counter.get()) {
                    Thread.sleep(10);
                }
            }
        }
    } finally {
        service.shutdown();
    }
}

প্রোগ্রামটি উপলভ্য মেমরিটিকে ক্লান্ত করে তোলে, যদিও এটি তৈরি হওয়াগুলি Runnableসম্পূর্ণ হওয়ার জন্য অপেক্ষা করে ।

আমি যদিও এটি সম্পর্কে কিছু সময়ের জন্য, কিন্তু দুর্ভাগ্যক্রমে আমি একটি ভাল সমাধান নিয়ে আসতে পারেনি।

সম্পাদনা: আমি জানতে পেরেছি যে এই সমস্যাটি জেডিকে বাগ 6602600 হিসাবে রিপোর্ট করা হয়েছিল এবং খুব সম্ভবত এটি সংশোধন করা হয়েছে বলে মনে হয়।


4

ফিউচারটাস্কে টাস্কটি মোড়ানো এবং আপনি ফিউচারটাস্কের সময়সীমা নির্দিষ্ট করতে পারেন। এই প্রশ্নের আমার উত্তরে উদাহরণটি দেখুন,

জাভা নেটিভ প্রক্রিয়া সময়সীমা


4
আমি বুঝতে পারি java.util.concurrentক্লাসগুলি ব্যবহার করে এটি করার কয়েকটি উপায় আছে তবে আমি একটি ExecutorServiceবাস্তবায়ন খুঁজছি ।
এডওয়ার্ড ডেল

4
আপনি যদি বলছেন যে আপনি নিজের এক্সিকিউটর সার্ভিসটিকে ক্লায়েন্ট কোড থেকে সময়সামগ্রী যুক্ত করা হচ্ছে তা গোপন করতে চান, আপনি কার্যকর করতে পারেন তার আগে চালিত প্রতিটি প্রবর্তককে ফিউচারটাস্ক দিয়ে গুটিয়ে রাখে এমন আপনার নিজের এক্সিকিউটর সার্ভিস প্রয়োগ করতে পারেন।
এরিকপ্রেস

2

সমীক্ষার জন্য অনেক সময় পরে,
পরিশেষে, আমি এই সমস্যাটি সমাধান করার invokeAllপদ্ধতিটি ব্যবহার করি ExecutorService
যা টাস্ক চলাকালীন কাজটিকে কঠোরভাবে বিঘ্নিত করবে।
এখানে উদাহরণ

ExecutorService executorService = Executors.newCachedThreadPool();

try {
    List<Callable<Object>> callables = new ArrayList<>();
    // Add your long time task (callable)
    callables.add(new VaryLongTimeTask());
    // Assign tasks for specific execution timeout (e.g. 2 sec)
    List<Future<Object>> futures = executorService.invokeAll(callables, 2000, TimeUnit.MILLISECONDS);
    for (Future<Object> future : futures) {
        // Getting result
    }
} catch (InterruptedException e) {
    e.printStackTrace();
}

executorService.shutdown();

সমর্থক আপনি ListenableFutureএকই সময়ে জমা দিতে পারেন ExecutorService
কোডের প্রথম লাইনটি সামান্য পরিবর্তন করুন।

ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());

ListeningExecutorServiceExecutorServiceগুগল পেয়ারা প্রকল্পের শ্রোতা বৈশিষ্ট্য ( com.google.guava )


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

1

Http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html তেExecutorService.shutDownNow() বর্ণিত পদ্ধতিটি কীভাবে ব্যবহার করবেন ? এটি সহজ সমাধান বলে মনে হচ্ছে।


8
কারণ এটি সমস্ত নির্ধারিত কাজগুলি থামিয়ে দেবে এবং কোনও নির্দিষ্ট কাজ নয় যেমনটি প্রশ্নের দ্বারা অনুরোধ করা হয়েছিল
মাইকএল

1

দেখে মনে হচ্ছে সমস্যাটি JDK বাগ 6602600 (এটি 2010-05-22-এ সমাধান করা হয়েছিল) নয়, তবে বৃত্তে ঘুমের ভুল কল (10)। সংযোজন নোট, যে বাহ্যিক বৃত্তের প্রতিটি শাখায় স্লাইপ (0) আহ্বান করে তৃতীয় কার্যগুলি উপলব্ধি করতে মূল থ্রেডটি অবশ্যই অন্য থ্রেডগুলিতে সরাসরি CHANCE দিতে হবে। থ্রেড.সিল্ড (0) এর পরিবর্তে থ্রেড.ইয়েল্ড () ব্যবহার করা ভাল বলে আমি মনে করি

পূর্ববর্তী সমস্যা কোডের ফলাফল সংশোধন করা অংশটি এরকম:

.......................
........................
Thread.yield();         

if (i % 1000== 0) {
System.out.println(i + "/" + counter.get()+ "/"+service.toString());
}

//                
//                while (i > counter.get()) {
//                    Thread.sleep(10);
//                } 

এটি 150,000 000 পর্যন্ত পরীক্ষিত চেনাশোনা পর্যন্ত বহিরাগত কাউন্টারের পরিমাণের সাথে সঠিকভাবে কাজ করে।


1

জন ডাব্লু উত্তর ব্যবহার করে আমি একটি বাস্তবায়ন তৈরি করেছি যা কার্য সম্পাদন শুরু করার সাথে সাথে টাইমআউটটি সঠিকভাবে শুরু করে। এমনকি আমি এর জন্য একটি ইউনিট পরীক্ষা লিখি :)

যাইহোক, এটি আমার প্রয়োজনগুলির সাথে খাপ খায় না কারণ কিছু আইও অপারেশন যখন Future.cancel()ডাকা হয় (যখন Thread.interrupt()বলা হয়) বাধা দেয় না । আইও অপারেশনের কয়েকটি উদাহরণ Thread.interrupt()যা বলা হয়ে গেলে বাধা দেওয়া হতে পারে না Socket.connectএবং Socket.read(এবং আমি সন্দেহ করি যে বেশিরভাগ আইও অপারেশন বাস্তবায়িত হয়েছিল java.io)। java.nioযখন Thread.interrupt()ডেকে আনা হয় তখন সমস্ত আইও অপারেশনগুলি বাধা দেওয়া উচিত । উদাহরণস্বরূপ, এটি ক্ষেত্রে SocketChannel.openএবং SocketChannel.read

যাইহোক যদি কেউ আগ্রহী হন, আমি থ্রেড পুল নির্বাহকের জন্য একটি সংক্ষেপ তৈরি করেছি যা কাজগুলি সময়সীমার জন্য মঞ্জুরি দেয় (যদি তারা বাধাদানযোগ্য অপারেশনগুলি ব্যবহার করে ...): https://gist.github.com/amanteaux/64c54a913c1ae34ad7b86db109cbc0bf


আকর্ষণীয় কোড, আমি এটিকে আমার সিস্টেমে টানলাম এবং কৌতূহলযুক্ত যদি আপনার কাছে কিছু উদাহরণ রয়েছে যা আইও ক্রিয়াকলাপ বাধাগ্রস্ত করবে না যাতে আমি এটি দেখতে পারি এটি আমার সিস্টেমে প্রভাব ফেলবে কিনা। ধন্যবাদ!
ডানকান ক্রেবস

@ ডানক্রেবস আমি আমার উত্তরটি অবিচ্ছিন্ন আইও এর উদাহরণ সহ বিস্তারিতভাবে বর্ণনা করেছি: Socket.connectএবংSocket.read
অ্যামেন্টেক্স

myThread.interrupted()বাধা দেওয়ার সঠিক পদ্ধতি নয়, কারণ এটি বাধাদান পতাকাটি পরিষ্কার করে। myThread.interrupt()পরিবর্তে ব্যবহার করুন, এবং এটি সকেটগুলির সাথে হওয়া উচিত
ড্যানিয়েলকুড্রা

@ ড্যানিয়েলকুড্রা: আপনাকে ধন্যবাদ, দেখে মনে হচ্ছে যে আমি কোনও টাইপ ভুল করেছি যেহেতু Thread.interrupted()কোনও থ্রেড বাধা দিতে সক্ষম করে না। তবে, অপারেশনগুলিতে Thread.interrupt()বাধা দেয় না java.io, এটি কেবল java.nioঅপারেশনগুলিতে কাজ করে।
অ্যান্টেউক্স

আমি interrupt()বহু বছর ধরে ব্যবহার করেছি এবং এটি সর্বদা java.io অপারেশনগুলিকে বাধা দেয় (পাশাপাশি অন্যান্য ব্লকিং পদ্ধতিগুলির মধ্যে যেমন থ্রেড স্লিপ, জেডিবিসি কানেকশনস, ব্লকিংকিউ নেওয়া ইত্যাদি)। সম্ভবত আপনি একটি বগী ক্লাস বা কিছু জেভিএম খুঁজে পেয়েছেন যাতে বাগ রয়েছে
ড্যানিয়েলকুড্রা

0

এই বিকল্প ধারণা সম্পর্কে কি:

  • দু'জনের দু'জন এক্সিকিউটার রয়েছে:
    • একের জন্য :
      • টাস্কের সময়সীমা সম্পর্কে চিন্তা না করে কাজটি জমা দেওয়া
      • ভবিষ্যত যোগ করার ফলাফল এবং সময়টি যখন এটি অভ্যন্তরীণ কাঠামোতে শেষ হয় end
    • একটি অভ্যন্তরীণ কাজ সম্পাদনের জন্য একটি যা অভ্যন্তরীণ কাঠামোটি পরীক্ষা করছে যদি কিছু কাজ সমাপ্ত হয় এবং যদি সেগুলি বাতিল করতে হয়।

ছোট নমুনা এখানে:

public class AlternativeExecutorService 
{

private final CopyOnWriteArrayList<ListenableFutureTask> futureQueue       = new CopyOnWriteArrayList();
private final ScheduledThreadPoolExecutor                scheduledExecutor = new ScheduledThreadPoolExecutor(1); // used for internal cleaning job
private final ListeningExecutorService                   threadExecutor    = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(5)); // used for
private ScheduledFuture scheduledFuture;
private static final long INTERNAL_JOB_CLEANUP_FREQUENCY = 1000L;

public AlternativeExecutorService()
{
    scheduledFuture = scheduledExecutor.scheduleAtFixedRate(new TimeoutManagerJob(), 0, INTERNAL_JOB_CLEANUP_FREQUENCY, TimeUnit.MILLISECONDS);
}

public void pushTask(OwnTask task)
{
    ListenableFuture<Void> future = threadExecutor.submit(task);  // -> create your Callable
    futureQueue.add(new ListenableFutureTask(future, task, getCurrentMillisecondsTime())); // -> store the time when the task should end
}

public void shutdownInternalScheduledExecutor()
{
    scheduledFuture.cancel(true);
    scheduledExecutor.shutdownNow();
}

long getCurrentMillisecondsTime()
{
    return Calendar.getInstance().get(Calendar.MILLISECOND);
}

class ListenableFutureTask
{
    private final ListenableFuture<Void> future;
    private final OwnTask                task;
    private final long                   milliSecEndTime;

    private ListenableFutureTask(ListenableFuture<Void> future, OwnTask task, long milliSecStartTime)
    {
        this.future = future;
        this.task = task;
        this.milliSecEndTime = milliSecStartTime + task.getTimeUnit().convert(task.getTimeoutDuration(), TimeUnit.MILLISECONDS);
    }

    ListenableFuture<Void> getFuture()
    {
        return future;
    }

    OwnTask getTask()
    {
        return task;
    }

    long getMilliSecEndTime()
    {
        return milliSecEndTime;
    }
}

class TimeoutManagerJob implements Runnable
{
    CopyOnWriteArrayList<ListenableFutureTask> getCopyOnWriteArrayList()
    {
        return futureQueue;
    }

    @Override
    public void run()
    {
        long currentMileSecValue = getCurrentMillisecondsTime();
        for (ListenableFutureTask futureTask : futureQueue)
        {
            consumeFuture(futureTask, currentMileSecValue);
        }
    }

    private void consumeFuture(ListenableFutureTask futureTask, long currentMileSecValue)
    {
        ListenableFuture<Void> future = futureTask.getFuture();
        boolean isTimeout = futureTask.getMilliSecEndTime() >= currentMileSecValue;
        if (isTimeout)
        {
            if (!future.isDone())
            {
                future.cancel(true);
            }
            futureQueue.remove(futureTask);
        }
    }
}

class OwnTask implements Callable<Void>
{
    private long     timeoutDuration;
    private TimeUnit timeUnit;

    OwnTask(long timeoutDuration, TimeUnit timeUnit)
    {
        this.timeoutDuration = timeoutDuration;
        this.timeUnit = timeUnit;
    }

    @Override
    public Void call() throws Exception
    {
        // do logic
        return null;
    }

    public long getTimeoutDuration()
    {
        return timeoutDuration;
    }

    public TimeUnit getTimeUnit()
    {
        return timeUnit;
    }
}
}

0

এটি আপনার জন্য কাজ করে কিনা তা পরীক্ষা করে দেখুন,

    public <T,S,K,V> ResponseObject<Collection<ResponseObject<T>>> runOnScheduler(ThreadPoolExecutor threadPoolExecutor,
      int parallelismLevel, TimeUnit timeUnit, int timeToCompleteEachTask, Collection<S> collection,
      Map<K,V> context, Task<T,S,K,V> someTask){
    if(threadPoolExecutor==null){
      return ResponseObject.<Collection<ResponseObject<T>>>builder().errorCode("500").errorMessage("threadPoolExecutor can not be null").build();
    }
    if(someTask==null){
      return ResponseObject.<Collection<ResponseObject<T>>>builder().errorCode("500").errorMessage("Task can not be null").build();
    }
    if(CollectionUtils.isEmpty(collection)){
      return ResponseObject.<Collection<ResponseObject<T>>>builder().errorCode("500").errorMessage("input collection can not be empty").build();
    }

    LinkedBlockingQueue<Callable<T>> callableLinkedBlockingQueue = new LinkedBlockingQueue<>(collection.size());
    collection.forEach(value -> {
      callableLinkedBlockingQueue.offer(()->someTask.perform(value,context)); //pass some values in callable. which can be anything.
    });
    LinkedBlockingQueue<Future<T>> futures = new LinkedBlockingQueue<>();

    int count = 0;

    while(count<parallelismLevel && count < callableLinkedBlockingQueue.size()){
      Future<T> f = threadPoolExecutor.submit(callableLinkedBlockingQueue.poll());
      futures.offer(f);
      count++;
    }

    Collection<ResponseObject<T>> responseCollection = new ArrayList<>();

    while(futures.size()>0){
      Future<T> future = futures.poll();
      ResponseObject<T> responseObject = null;
        try {
          T response = future.get(timeToCompleteEachTask, timeUnit);
          responseObject = ResponseObject.<T>builder().data(response).build();
        } catch (InterruptedException e) {
          future.cancel(true);
        } catch (ExecutionException e) {
          future.cancel(true);
        } catch (TimeoutException e) {
          future.cancel(true);
        } finally {
          if (Objects.nonNull(responseObject)) {
            responseCollection.add(responseObject);
          }
          futures.remove(future);//remove this
          Callable<T> callable = getRemainingCallables(callableLinkedBlockingQueue);
          if(null!=callable){
            Future<T> f = threadPoolExecutor.submit(callable);
            futures.add(f);
          }
        }

    }
    return ResponseObject.<Collection<ResponseObject<T>>>builder().data(responseCollection).build();
  }

  private <T> Callable<T> getRemainingCallables(LinkedBlockingQueue<Callable<T>> callableLinkedBlockingQueue){
    if(callableLinkedBlockingQueue.size()>0){
      return callableLinkedBlockingQueue.poll();
    }
    return null;
  }

আপনি শিডিয়ুলারের কাছ থেকে থ্রেড ব্যবহারের সংখ্যাকে সীমাবদ্ধ করতে পারেন এবং সেইসাথে কার্যের সময়সীমাও রেখে দিতে পারেন।

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