একটি আকার সীমা দিয়ে ক্যাশেড থ্রেড পুল তৈরি করা অসম্ভব?


127

এটি যতটা থ্রেড তৈরি করতে পারে তার সীমাবদ্ধতার সাথে ক্যাশেড থ্রেড পুল তৈরি করা অসম্ভব বলে মনে হচ্ছে।

স্থিতি এক্সিকিউটার্স.নিউচ্যাচডথ্রেডপুলটি কীভাবে স্ট্যান্ডার্ড জাভা লাইব্রেরিতে প্রয়োগ করা হয় তা এখানে:

 public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

সুতরাং, নির্দিষ্ট আকারের ক্যাশেড থ্রেড পুল তৈরি করতে সেই টেম্পলেটটি ব্যবহার করে:

new ThreadPoolExecutor(0, 3, 60L, TimeUnit.SECONDS, new SynchronusQueue<Runable>());

এখন আপনি যদি এটি ব্যবহার করেন এবং 3 টি কাজ জমা দেন তবে সবকিছু ঠিকঠাক হবে। পরবর্তী কোনও কাজ জমা দেওয়ার ফলস্বরূপ প্রত্যাখ্যানযোগ্য বাতিল হয়েছে।

এটি চেষ্টা করে:

new ThreadPoolExecutor(0, 3, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runable>());

সমস্ত থ্রেড ক্রমান্বয়ে কার্যকর করা হবে। অর্থাৎ, থ্রেড পুলটি আপনার কাজগুলি পরিচালনা করতে কখনও একের বেশি থ্রেড তৈরি করে না।

এটি থ্রেডপুলএক্সেকিউটারের এক্সিকিউট পদ্ধতিতে একটি বাগ? নাকি এই ইচ্ছাকৃত? বা অন্য কোন উপায় আছে?

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


1
আপনার প্রশ্ন কি? আপনার ২ য় কোড উদাহরণটি কি আপনার শিরোনামের উত্তর নয়?
আরএসপি

4
আমি একটি থ্রেড পুল চাই যা কাজের সংখ্যা বাড়ার সাথে সাথে থ্রেড যুক্ত করবে, তবে কখনও কখনও সর্বোচ্চ সংখ্যক থ্রেডের বেশি যোগ করা হবে না। ক্যাশেড্রেডপুল ইতিমধ্যে এটি করেছে, এটি সীমাহীন সংখ্যক থ্রেড যুক্ত করবে এবং কিছু প্রাক-সংজ্ঞায়িত আকারে থামবে না। উদাহরণগুলিতে আমি যে আকারটি সংজ্ঞা দিয়েছি তা হ'ল ৩ য় দ্বিতীয় উদাহরণটি ১ টি থ্রেড যুক্ত করে, তবে অন্যান্য টাস্কগুলি এখনও সম্পন্ন না হওয়ার সাথে সাথে নতুন কার্যগুলি উপস্থিত হওয়ার সাথে সাথে আরও দুটি যুক্ত করে না।
ম্যাট ক্রিঙ্কলা-ভোগ

এটি পরীক্ষা করে দেখুন, এটি সমাধান করে, debuggingisfun.blogspot.com/2012/05/…
ইথান

এর সাথে সম্পর্কিত: স্ট্যাকওভারফ্লো.com
ধূসর

উত্তর:


235

থ্রেডপুলএকসিকিউটারের নিম্নলিখিত কয়েকটি মূল আচরণ রয়েছে এবং আপনার সমস্যাগুলি এই আচরণগুলি দ্বারা ব্যাখ্যা করা যেতে পারে।

যখন কাজগুলি জমা দেওয়া হয়,

  1. যদি থ্রেড পুলটি মূল আকারে না পৌঁছে, তবে এটি নতুন থ্রেড তৈরি করে।
  2. যদি মূল আকারটি পৌঁছে যায় এবং কোনও নিষ্ক্রিয় থ্রেড না থাকে তবে এটি কার্যগুলি সারি করে।
  3. যদি মূল আকারটি পৌঁছে যায় তবে কোনও অলস থ্রেড নেই, এবং সারিটি পূর্ণ হয়ে যায়, এটি নতুন থ্রেড তৈরি করে (এটি সর্বোচ্চ আকারে না পৌঁছানো পর্যন্ত)।
  4. যদি সর্বোচ্চ আকারটি পৌঁছে যায় তবে কোনও অলস থ্রেড নেই এবং সারিটি পূর্ণ হয়ে যায়, প্রত্যাখ্যান নীতিটি কিক করে।

প্রথম উদাহরণে, মনে রাখবেন যে সিঙ্ক্রোনাস কিউইউর মূল আকার 0 রয়েছে Therefore সুতরাং, আপনি যখন সর্বোচ্চ আকার (3) এ পৌঁছবেন, সেই প্রত্যাখ্যান নীতিটি (# 4) কিক করে।

দ্বিতীয় উদাহরণে, পছন্দের সারিটি একটি লিংকড ব্লকিংকিউ যা সীমাহীন আকারের। অতএব, আপনি আচরণ # 2 এ আটকে যান।

ক্যাশেড টাইপ বা নির্দিষ্ট ধরণের সাথে আপনি সত্যিকার অর্থে খুব বেশি ঝাঁকুনি দিতে পারবেন না কারণ তাদের আচরণ প্রায় সম্পূর্ণ নির্ধারিত।

আপনি যদি একটি সীমাবদ্ধ এবং গতিশীল থ্রেড পুল রাখতে চান তবে আপনাকে সীমাবদ্ধ আকারের একটি সারির সাথে মিলিয়ে একটি ধনাত্মক কোর আকার এবং সর্বাধিক আকার ব্যবহার করতে হবে। উদাহরণ স্বরূপ,

new ThreadPoolExecutor(10, // core size
    50, // max size
    10*60, // idle timeout
    TimeUnit.SECONDS,
    new ArrayBlockingQueue<Runnable>(20)); // queue with a size

সংযোজন : এটি মোটামুটি পুরানো উত্তর, এবং এটি উপস্থিত হয় যে এটি 0 আকারের মূল আকারে আসে যখন JDK তার আচরণ পরিবর্তন করেছে, যেহেতু জেডিকে 1.6, মূল আকারটি 0 এবং পুলটিতে কোনও থ্রেড না থাকলে থ্রেডপুলএক্সেকিউটার যুক্ত করবে থ্রেড যে কার্য সম্পাদন। সুতরাং, 0 এর মূল আকারটি উপরের নিয়মের ব্যতিক্রম। এটি আমার নজরে আনার জন্য স্টিভকে ধন্যবাদ জানাই


4
allowCoreThreadTimeOutএই উত্তরটি নিখুঁত করতে আপনাকে অবশ্যই পদ্ধতি সম্পর্কে কয়েকটি শব্দ লিখতে হবে । @ User1046052 উত্তর দেখুন
hsestupin

1
দুর্দান্ত উত্তর! মাত্র একটি পয়েন্ট যোগ করুন: অন্যান্য প্রত্যাখ্যান নীতিগুলিও উল্লেখ করার মতো। @ ব্রায়ানেগের উত্তর দেখুন
জেফ

1
আচরণ 2 বলা উচিত নয় 'যদি ম্যাক্সথ্রেড আকার পৌঁছে যায় এবং কোনও নিষ্ক্রিয় থ্রেড না থাকে তবে এটি কার্যগুলি সারি করে।' ?
জুলটান

1
আপনি কি কি সারির আকারটি বোঝাতে পারেন তা ব্যাখ্যা করতে পারেন? এর অর্থ কি এই যে 20 টি কাজ প্রত্যাখ্যান হওয়ার আগেই তাদের সারিবদ্ধ করা যেতে পারে?
জুলটান

1
@ জোল্টন আমি কিছুক্ষণ আগে এটি লিখেছিলাম, সুতরাং এর পরে কিছু আচরণের পরিবর্তন হওয়ার সম্ভাবনা রয়েছে (আমি সর্বশেষ ক্রিয়াকলাপগুলি খুব ঘনিষ্ঠভাবে অনুসরণ করি নি), তবে এই আচরণগুলি অপরিবর্তিত বলে ধরে নিয়েছি, # 2 সঠিকভাবে বলা হয়েছে, এবং এটিই সম্ভবত এটির সবচেয়ে গুরুত্বপূর্ণ (এবং কিছুটা অবাক করা) বিষয়। মূল আকারটি পৌঁছে গেলে, টিপিই নতুন থ্রেড তৈরি করার পক্ষে সারিবদ্ধভাবে সমর্থন করে। টিপিতে পাস করা কাতারের আকারটি আক্ষরিক আকারের ue যদি সারিটি পূর্ণ হয়ে যায় তবে এটি সর্বোচ্চ আকারে পৌঁছায় না, এটি একটি নতুন থ্রেড তৈরি করবে (কার্যগুলি প্রত্যাখ্যান করবে না)। # 3 দেখুন। আশা করি এইটি কাজ করবে.
1'16

60

আমি যদি কিছু মিস না করি তবে মূল প্রশ্নের সমাধানটি সহজ। মূল পোস্টার দ্বারা বর্ণিত হিসাবে নিম্নলিখিত কোডটি পছন্দসই আচরণ প্রয়োগ করে। আনবাউন্ডেড কাতারে কাজ করার জন্য এটি 5 টি থ্রেড পর্যন্ত স্প্যান করবে এবং নিষ্ক্রিয় থ্রেডগুলি 60 সেকেন্ড পরে শেষ হবে।

tp = new ThreadPoolExecutor(5, 5, 60, TimeUnit.SECONDS,
                    new LinkedBlockingQueue<Runnable>());
tp.allowCoreThreadTimeOut(true);

1
আপনি সঠিক. এই পদ্ধতিটি jdk 1.6 এ যুক্ত করা হয়েছিল, তাই এটি সম্পর্কে অনেকেই জানেন না। এছাড়াও, আপনার কাছে একটি "মিনিট" কোর পুলের আকার থাকতে পারে না, যা দুর্ভাগ্যজনক।
jtahlorn

4
এ সম্পর্কে আমার একমাত্র উদ্বেগ হ'ল (জেডিকে 8 ডক্স থেকে): "যখন পদ্ধতিতে এক্সিকিউট করা (চালানোযোগ্য) তে কোনও নতুন কাজ জমা দেওয়া হয় এবং কোরপুল সাইজের থ্রেডের চেয়ে কম চালানো হয়, অনুরোধটি পরিচালনা করার জন্য একটি নতুন থ্রেড তৈরি করা হয়, এমনকি অন্য কর্মী হলেও থ্রেডগুলি অলস "
ভিজি

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

2
এটি কাজ করে, ম্যাট। আপনি মূল আকারটি 0 তে সেট করেছেন, এজন্য আপনার কেবল 1 টি থ্রেড ছিল। এখানে কৌশলটি হ'ল মূল আকারটি সর্বোচ্চ আকারে সেট করা to
টি-জারগলি

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

7

একই সমস্যা ছিল। যেহেতু অন্য কোনও উত্তর সমস্ত বিষয় একসাথে রাখে না, তাই আমি আমার যুক্ত করছি:

এটা এখন স্পষ্ট লেখা আছে ডক্স : আপনি একটি সারিতে যে অবরোধের (না ব্যবহার করেন তাহলে LinkedBlockingQueue) সর্বোচ্চ থ্রেড সেটিং কোনো প্রভাব নেই, শুধুমাত্র কোর থ্রেড ব্যবহার করা হয়।

তাই:

public class MyExecutor extends ThreadPoolExecutor {

    public MyExecutor() {
        super(4, 4, 5,TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
        allowCoreThreadTimeOut(true);
    }

    public void setThreads(int n){
        setMaximumPoolSize(Math.max(1, n));
        setCorePoolSize(Math.max(1, n));
    }

}

এই নির্বাহকের রয়েছে:

  1. আমরা আনবাউন্ডেড সারি ব্যবহার করায় সর্বোচ্চ থ্রেডের কোনও ধারণা নেই। এটি একটি ভাল জিনিস কারণ এই জাতীয় সারি কার্যকর নীতি অনুসরণ করে যদি এক্সিকিউটারকে প্রচুর পরিমাণে নন-কোর, অতিরিক্ত থ্রেড তৈরি করতে পারে।

  2. সর্বাধিক আকারের একটি সারি Integer.MAX_VALUE। মুলতুবি থাকা কাজের সংখ্যা অতিক্রম করলে Submit()নিক্ষেপ করবে । নিশ্চিত নয় যে আমরা প্রথমে মেমরিটি শেষ করে দেব বা এটি ঘটবে।RejectedExecutionExceptionInteger.MAX_VALUE

  3. 4 টি মূল থ্রেড সম্ভব রয়েছে। নিষ্কলঙ্ক মূল থ্রেডগুলি স্বয়ংক্রিয়ভাবে 5 সেকেন্ডের জন্য নিষ্ক্রিয় হলে প্রস্থান করে o সুতরাং, হ্যাঁ, কঠোরভাবে চাহিদা থ্রেডগুলিতে N সংখ্যাটি setThreads()পদ্ধতি ব্যবহার করে বিভিন্ন রকম হতে পারে ।

  4. নিশ্চিত করুন যে নূন্যতম মূল থ্রেডগুলির সংখ্যা কখনই একের চেয়ে কম নয়, অন্যথায় submit()প্রতিটি কাজ প্রত্যাখ্যান করবে। যেহেতু মূল থ্রেডগুলি হওয়া প্রয়োজন = = সর্বোচ্চ থ্রেডগুলি পদ্ধতিটি setThreads()সর্বোচ্চ থ্রেডগুলিও সেট করে, যদিও সর্বাধিক থ্রেড সেটিংস আনবাউন্ডেড কিউয়ের জন্য অকেজো।


আমি মনে করি আপনারও 'অনুমতিকুরিথ্রেডটাইম' সেটকে 'সত্য' হিসাবে সেট করা দরকার, অন্যথায়, থ্রেডগুলি তৈরি হয়ে গেলে, আপনি এগুলি চিরকাল ধরে রাখবেন: gist.github.com/ericdcob/46b817b384f5ca9d5f5d
এরিক

উফ আমি ঠিক এটাই মিস করেছি, দুঃখিত, আপনার উত্তরটি তখন নিখুঁত!
এরিক

6

আপনার প্রথম উদাহরণে, পরবর্তী কাজগুলি প্রত্যাখ্যান করা হয়েছে কারণ AbortPolicyএটি ডিফল্ট RejectedExecutionHandler। থ্রেডপুলএ্যাক্সিকিউটরটিতে নিম্নলিখিত নীতিগুলি রয়েছে, যা আপনি setRejectedExecutionHandlerপদ্ধতিটির মাধ্যমে পরিবর্তন করতে পারবেন :

CallerRunsPolicy
AbortPolicy
DiscardPolicy
DiscardOldestPolicy

দেখে মনে হচ্ছে আপনি কলারআনসপলিসি সহ ক্যাশেড থ্রেড পুল চান।


5

এখানকার উত্তরের কোনও উত্তরই আমার সমস্যাটির সমাধান করতে পারেনি, যা অ্যাপাচের এইচটিটিপি ক্লায়েন্ট (3.x সংস্করণ) ব্যবহার করে সীমিত পরিমাণে এইচটিটিপি সংযোগ তৈরি করতে হয়েছিল। যেহেতু ভাল সেটআপটি বের করতে আমার কয়েক ঘন্টা লেগেছিল, তাই আমি ভাগ করে নেব:

private ExecutorService executor = new ThreadPoolExecutor(5, 10, 60L,
  TimeUnit.SECONDS, new SynchronousQueue<Runnable>(),
  Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());

এটি এমন একটি তৈরি করে ThreadPoolExecutorযা পাঁচটি দিয়ে শুরু হয় এবং CallerRunsPolicyকার্যকর করার জন্য ব্যবহার করে সর্বোচ্চ দশটি একযোগে চলমান থ্রেড ধারণ করে ।


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

3

থ্রেডপুলএকসিকিউটারের জন্য জাভাডোক:

আরো corePoolSize চেয়ে কিন্তু চেয়ে maximumPoolSize থ্রেড চলমান কম হয়, তাহলে একটি নতুন থ্রেড তৈরি করা হবে শুধুমাত্র যদি কিউ পূর্ণ । কোরপুল সাইজ এবং ম্যাক্সিমুলপুল সাইজ একই সেট করে আপনি একটি স্থির আকারের থ্রেড পুল তৈরি করেন।

(জোর আমার।)

জিটারের উত্তরটি আপনি যা চান তা হ'ল যদিও আমার আপনার অন্য প্রশ্নের উত্তর দেয়। :)


2

আরও একটি বিকল্প আছে। নতুন সিঙ্ক্রোনাস কিউ ব্যবহার না করে আপনি অন্য যে কোনও সারিও ব্যবহার করতে পারেন, তবে আপনাকে এটির আকার 1 হবে তা নিশ্চিত করতে হবে, যা এক্সিকিউটার্স সার্ভিসকে নতুন থ্রেড তৈরি করতে বাধ্য করবে।


আমি মনে করি আপনার আকার 0 (ডিফল্টরূপে) বলতে বোঝায়, যাতে কোনও কাজ সারিবদ্ধ না হয় এবং প্রতিটি সময় নতুন থ্রেড তৈরি করতে এক্সিকিউটর সার্ভিসটিকে সত্যই জোর করে।
লিওনম্যাক্স

2

দেখে মনে হচ্ছে না যে কোনও উত্তর আসলে প্রশ্নের উত্তর দেয় - বাস্তবে আমি এটি করার কোনও উপায় দেখতে পাচ্ছি না - এমনকি আপনি যদি পুলডএক্সেকিউটারসেবা থেকে সাবক্লাস করেন যেহেতু অনেকগুলি পদ্ধতি / বৈশিষ্ট্য ব্যক্তিগত যেমন eg নিম্নলিখিতটি করুন:

class MyThreadPoolService extends ThreadPoolService {
    public void execute(Runnable run) {
        if (poolSize() == 0) {
            if (addIfUnderMaximumPoolSize(run) != null)
                return;
        }
        super.execute(run);
    }
}

আমার কাছে সবচেয়ে কাছেরটি এটি ছিল - তবে এটি খুব ভাল সমাধান নয়

new ThreadPoolExecutor(min, max, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()) {
    public void execute(Runnable command) {
        if (getPoolSize() == 0 && getActiveCount() < getMaximumPoolSize()) {        
            super.setCorePoolSize(super.getCorePoolSize() + 1);
        }
        super.execute(command);
    }

    protected void afterExecute(Runnable r, Throwable t) {
         // nothing in the queue
         if (getQueue().isEmpty() && getPoolSize() > min) {
             setCorePoolSize(getCorePoolSize() - 1);
         }
    };
 };

PS উপরের পরীক্ষা করা হয়নি


2

এখানে আরও একটি সমাধান দেওয়া হল। আমি মনে করি এই সমাধানটি আপনি যেমন চান তেমন আচরণ করে (যদিও এই সমাধানটি নিয়ে গর্বিত নন):

final LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>() {
    public boolean offer(Runnable o) {
        if (size() > 1)
            return false;
        return super.offer(o);
    };

    public boolean add(Runnable o) {
        if (super.offer(o))
            return true;
        else
            throw new IllegalStateException("Queue full");
    }
};

RejectedExecutionHandler handler = new RejectedExecutionHandler() {         
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        queue.add(r);
    }
};

dbThreadExecutor =
        new ThreadPoolExecutor(min, max, 60L, TimeUnit.SECONDS, queue, handler);

2

এটি আপনি চান (অন্তত আমি অনুমান করি)। ব্যাখ্যার জন্য জোনাথন ফিনবার্গের উত্তরটি দেখুন

Executors.newFixedThreadPool(int n)

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


4
অবশ্যই, আমি একটি স্থির থ্রেড পুল ব্যবহার করতে পারতাম তবে এটি চিরকালের জন্য, বা আমি শাটডাউন না করা অবধি থ্রেডগুলি ছেড়ে দেব। আমি একেবারে ক্যাশেড থ্রেড পুলের মতো কিছু চাই (এটি চাহিদা অনুসারে থ্রেড তৈরি করে এবং পরে কিছু সময়সীমা শেষ করে এগুলি হত্যা করে) তবে এটি তৈরি করতে পারে এমন সংখ্যার সীমা নিয়ে with
ম্যাট ক্রিঙ্কলা-ভোগ

0
  1. তুমি ব্যবহার করতে পার ThreadPoolExecutor প্রস্তাবিত হিসাবে @ sjlee

    আপনি গতির দিক দিয়ে পুলের আকারটি নিয়ন্ত্রণ করতে পারেন। আরও বিশদ জানতে এই প্রশ্নটি দেখুন:

    ডায়নামিক থ্রেড পুল

    অথবা

  2. আপনি জাভা 8 এর সাথে চালু করা নতুন ওয়ার্কস্টেলিংপুল API ব্যবহার করতে পারেন ।

    public static ExecutorService newWorkStealingPool()

    সমস্ত উপলভ্য প্রসেসরকে তার লক্ষ্য সমান্তরালতা স্তর হিসাবে ব্যবহার করে একটি ওয়ার্ক-স্টিলিং থ্রেড পুল তৈরি করে।

ডিফল্টরূপে, সমান্তরালতা স্তরটি আপনার সার্ভারে সিপিইউ কোরের সংখ্যায় সেট করা আছে। আপনি 4 কোর CPU- র সার্ভার থেকে থাকে থ্রেড পুল আকার 4. এই API আয় হবে ForkJoinPoolএর টাইপ ExecutorService এবং ForkJoinPool ব্যস্ত থ্রেড থেকে কর্ম চুরি করে অলস থ্রেডের কাজ চুরি অনুমতি দেয়।


0

সমস্যাটি সংক্ষেপে নিম্নরূপ করা হয়েছিল:

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

সমাধানের দিকে ইঙ্গিত করার আগে আমি নীচের সমাধানগুলি কেন কাজ করে না তা ব্যাখ্যা করব:

new ThreadPoolExecutor(0, 3, 60L, TimeUnit.SECONDS, new SynchronousQueue<>());

3 টির সীমা পৌঁছে গেলে এটি কোনও কাজকে সারি করবে না কারণ সংজ্ঞায়িতভাবে সিঙ্ক্রোনাসকুইউ কোনও উপাদান ধরে রাখতে পারে না।

new ThreadPoolExecutor(0, 3, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>());

এটি একক থ্রেডের চেয়ে বেশি তৈরি করতে পারে না কারণ থ্রেডপুলএ্যাক্সিকিউটর কেবল সারি পূর্ণ হলে কোরপুল সাইজ ছাড়িয়ে থ্রেড তৈরি করে que তবে লিংকডব্লকিংকিউ কখনই পূর্ণ হয় না।

ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 3, 60, TimeUnit.SECONDS,
    new LinkedBlockingQueue<Runnable>());
executor.allowCoreThreadTimeOut(true);

কোরপুলসাইজ না হওয়া পর্যন্ত এটি থ্রেডগুলি পুনরায় ব্যবহার করবে না কারণ থ্রেডপুলএক্সেকিউটার বিদ্যমান থ্রেডগুলি নিষ্ক্রিয় থাকলেও কোরপুল সাইজ না পাওয়া পর্যন্ত থ্রেডের সংখ্যা বাড়ায়। আপনি যদি এই অসুবিধা নিয়ে বেঁচে থাকতে পারেন তবে এটিই সমস্যার সহজ সমাধান। এটি "অনুশীলনে জাভা কনকুরન્સી" (পি 172-র পাদটীকা) এও বর্ণিত সমাধান।

বর্ণিত সমস্যার একমাত্র সম্পূর্ণ সমাধানটি মনে হয় যে সারিটিরoffer পদ্ধতিটি ওভাররাইডিং এবং RejectedExecutionHandlerএই প্রশ্নের উত্তরে বর্ণিত হিসাবে একটি লেখার সাথে জড়িত : কীভাবে সারি সরে যাওয়ার আগে থ্রেডপুলএক্সিকিটারকে সর্বোচ্চটি থ্রেড বাড়ানো যায়?


0

এটি জাভা 8 + এর জন্য কাজ করে (এবং অন্যান্য, আপাতত ..)

     Executor executor = new ThreadPoolExecutor(3, 3, 5, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>()){{allowCoreThreadTimeOut(true);}};

যেখানে 3 থ্রেড গণনার সীমা, এবং 5 নিষ্ক্রিয় থ্রেডের মেয়াদ উত্তীর্ণ।

আপনি যদি এটি নিজে কাজ করে কিনা তা পরীক্ষা করতে চান , কাজটি করার কোডটি এখানে:

public static void main(String[] args) throws InterruptedException {
    final int DESIRED_NUMBER_OF_THREADS=3; // limit of number of Threads for the task at a time
    final int DESIRED_THREAD_IDLE_DEATH_TIMEOUT=5; //any idle Thread ends if it remains idle for X seconds

    System.out.println( java.lang.Thread.activeCount() + " threads");
    Executor executor = new ThreadPoolExecutor(DESIRED_NUMBER_OF_THREADS, DESIRED_NUMBER_OF_THREADS, DESIRED_THREAD_IDLE_DEATH_TIMEOUT, TimeUnit.SECONDS,
            new LinkedBlockingQueue<>()) {{allowCoreThreadTimeOut(true);}};

    System.out.println(java.lang.Thread.activeCount() + " threads");

    for (int i = 0; i < 5; i++) {
        final int fi = i;
        executor.execute(() -> waitsout("starting hard thread computation " + fi, "hard thread computation done " + fi,2000));
    }
    System.out.println("If this is UP, it works");

    while (true) {
        System.out.println(
                java.lang.Thread.activeCount() + " threads");
        Thread.sleep(700);
    }

}

static void waitsout(String pre, String post, int timeout) {
    try {
        System.out.println(pre);
        Thread.sleep(timeout);
        System.out.println(post);
    } catch (Exception e) {
    }
}

আমার জন্য উপরের কোড আউটপুট হয়

1 threads
1 threads
If this is UP, it works
starting hard thread computation 0
4 threads
starting hard thread computation 2
starting hard thread computation 1
4 threads
4 threads
hard thread computation done 2
hard thread computation done 0
hard thread computation done 1
starting hard thread computation 3
starting hard thread computation 4
4 threads
4 threads
4 threads
hard thread computation done 3
hard thread computation done 4
4 threads
4 threads
4 threads
4 threads
3 threads
3 threads
3 threads
1 threads
1 threads
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.