Java中的自定义线程池实现

时间:2019-09-14 12:06:38

标签: java multithreading synchronization threadpool

出于倾斜的目的,我试图在Java中实现自己的线程池。以下是我实现的内容。我对此实施有几个疑问:

  1. 尽管我使用的是内置Java的BlockingQueue,但执行人员希望我们提供Runnable对象(通过execute方法)。但就我而言,我觉得我可以创建任何对象而不是Runnable。那么,为什么Java执行者期望Runnable,我尝试研究源代码,但还没有弄清楚。

  2. 这个原始实现还有其他问题吗?

请找到代码。

公共类CustomThreadPool {

private final BlockingQueue<Runnable> blockingQueue;
private final Worker[] workers;

public CustomThreadPool(final int numOfThreads) {
    blockingQueue = new LinkedBlockingQueue<>();
    workers = new Worker[numOfThreads];

    for (int i = 0; i < numOfThreads; i++) {
        workers[i] = new Worker();
        workers[i].start();
    }
}

public void execute(final Runnable task) {
    blockingQueue.add(task);
}

public void shutdownImmediately() {
    for (int i = 0; i < workers.length; i++) {
        workers[i].shutdownSignal = true;
        workers[i] = null;
    }
}

 private class Worker extends Thread {
    private Runnable taskToPerform = null;
    boolean shutdownSignal = false;

    @Override
    public void run() {
        while(true && !shutdownSignal) {
            taskToPerform = blockingQueue.poll();
            if (taskToPerform != null) {
                taskToPerform.run();
            }
            if(shutdownSignal) {
                break;
            }
        }
    }
}

public static void main(String[] args) throws Exception {
    final CustomThreadPool threadPool = new CustomThreadPool(5);
    for (int i = 0; i < 20; i++) {
        threadPool.execute(() -> System.out.println(Thread.currentThread().getName()));
    }
    Thread.sleep(1*1000);
    threadPool.shutdownImmediately();
}

}

1 个答案:

答案 0 :(得分:3)

  1. 执行器期望Runnable或Callable,因为它在运行您提交的任务时将调用这些接口的runcall方法。

  2. 在您的实现中,您不会使用BlockingQueue的阻塞方面。当您的队列中没有任务时,您的线程池线程将在while(true && !shutdownSignal)循环中不断旋转(占用CPU时间)。因为poll()方法没有阻塞。而这并不是实现线程池时想要的。

您应使用一种阻止方法,而不要使用poll()

您可以使用poll(long timeout,TimeUnit unit)方法来获取超时参数。在这种情况下,如果在任何线程池线程等待此调用的同时调用shutdownImmediately方法。他们将等待超时时间,民意调查将向他们返回null。他们将看到设置了shutdownSignal并退出了循环。如果您不希望他们等待超时,也可以调用中断方法。

 // in run method
 try {
     taskToPerform = blockingQueue.poll(5, TimeUnit.SECONDS);
 } catch (InterruptedException e) {
     break; // this thread is interrupted. Time to leave this loop
 }

// in shutdownImmediately method 
workers[i].shutdownSignal = true;
// If You don't call interrupt, Threads will wait at max 5 sec for this case.
workers[i].interrupt(); 
workers[i] = null;

或者您可以使用take()方法在队列中没有任何内容时阻塞。但是在这种情况下,当您调用shutdownImmediately方法时,您必须中断可能正在等待take方法调用的线程。否则,它们将卡在take()调用中。

// in run method
try {
   taskToPerform = blockingQueue.take();
} catch (InterruptedException e) {
   break; // this thread is interrupted. Time to leave this loop
}

// in shutdownImmediately method 
workers[i].shutdownSignal = true;
workers[i].interrupt(); // this is crucial for this case
workers[i] = null;