বালুসসি প্রদত্ত সমাধানে মূল থ্রেড সময়সীমার জন্য অবরুদ্ধ থাকবে। যদি আপনার একাধিক থ্রেড সহ একটি থ্রেড পুল থাকে তবে আপনার একই সংখ্যক অতিরিক্ত থ্রেডের প্রয়োজন হবে যা ফিউচার.জেট (দীর্ঘকালীন, টাইমউনিট ইউনিট) ব্লকিং কলটি সময়সীমার চেয়ে বেশি হলে থ্রেডটি অপেক্ষা করতে এবং বন্ধ করতে ব্যবহার করবে ।
এই সমস্যার জেনেরিক সমাধান হ'ল একটি থ্রেডপুলএক্সেকিউটার ডেকরেটার তৈরি করা যা টাইম আউট কার্যকারিতা যুক্ত করতে পারে। এই ডেকোরেটর শ্রেণিতে থ্রেডপুলএক্সেকিউটারের যতগুলি থ্রেড তৈরি করা উচিত এবং থ্রেডপুলএকসিকিউটারকে কেবল অপেক্ষা করতে এবং বন্ধ করতে এই সমস্ত থ্রেড ব্যবহার করা উচিত।
জেনেরিক ক্লাসটি নীচের মতো প্রয়োগ করা উচিত:
import java.util.List;
import java.util.concurrent.*;
public class TimeoutThreadPoolDecorator extends ThreadPoolExecutor {
private final ThreadPoolExecutor commandThreadpool;
private final long timeout;
private final TimeUnit unit;
public TimeoutThreadPoolDecorator(ThreadPoolExecutor threadpool,
long timeout,
TimeUnit unit ){
super( threadpool.getCorePoolSize(),
threadpool.getMaximumPoolSize(),
threadpool.getKeepAliveTime(TimeUnit.MILLISECONDS),
TimeUnit.MILLISECONDS,
threadpool.getQueue());
this.commandThreadpool = threadpool;
this.timeout=timeout;
this.unit=unit;
}
@Override
public void execute(Runnable command) {
super.execute(() -> {
Future<?> future = commandThreadpool.submit(command);
try {
future.get(timeout, unit);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (ExecutionException | TimeoutException e) {
throw new RejectedExecutionException(e);
} finally {
future.cancel(true);
}
});
}
@Override
public void setCorePoolSize(int corePoolSize) {
super.setCorePoolSize(corePoolSize);
commandThreadpool.setCorePoolSize(corePoolSize);
}
@Override
public void setThreadFactory(ThreadFactory threadFactory) {
super.setThreadFactory(threadFactory);
commandThreadpool.setThreadFactory(threadFactory);
}
@Override
public void setMaximumPoolSize(int maximumPoolSize) {
super.setMaximumPoolSize(maximumPoolSize);
commandThreadpool.setMaximumPoolSize(maximumPoolSize);
}
@Override
public void setKeepAliveTime(long time, TimeUnit unit) {
super.setKeepAliveTime(time, unit);
commandThreadpool.setKeepAliveTime(time, unit);
}
@Override
public void setRejectedExecutionHandler(RejectedExecutionHandler handler) {
super.setRejectedExecutionHandler(handler);
commandThreadpool.setRejectedExecutionHandler(handler);
}
@Override
public List<Runnable> shutdownNow() {
List<Runnable> taskList = super.shutdownNow();
taskList.addAll(commandThreadpool.shutdownNow());
return taskList;
}
@Override
public void shutdown() {
super.shutdown();
commandThreadpool.shutdown();
}
}
উপরের সাজসজ্জারটি নীচের হিসাবে ব্যবহার করা যেতে পারে:
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args){
long timeout = 2000;
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(3, 10, 0, TimeUnit.MILLISECONDS, new SynchronousQueue<>(true));
threadPool = new TimeoutThreadPoolDecorator( threadPool ,
timeout,
TimeUnit.MILLISECONDS);
threadPool.execute(command(1000));
threadPool.execute(command(1500));
threadPool.execute(command(2100));
threadPool.execute(command(2001));
while(threadPool.getActiveCount()>0);
threadPool.shutdown();
}
private static Runnable command(int i) {
return () -> {
System.out.println("Running Thread:"+Thread.currentThread().getName());
System.out.println("Starting command with sleep:"+i);
try {
Thread.sleep(i);
} catch (InterruptedException e) {
System.out.println("Thread "+Thread.currentThread().getName()+" with sleep of "+i+" is Interrupted!!!");
return;
}
System.out.println("Completing Thread "+Thread.currentThread().getName()+" after sleep of "+i);
};
}
}