Java 具有ArrayBlockingQueue的ThreadPoolExecutor

Java 具有ArrayBlockingQueue的ThreadPoolExecutor,java,multithreading,threadpool,executorservice,Java,Multithreading,Threadpool,Executorservice,在我的一个项目中使用ThreadPoolExecutor时,我开始从Java文档中阅读更多关于ThreadPoolExecutor的内容。有人能解释一下这条线的实际含义吗?-我知道每个参数代表什么,但我想从这里的一些专家那里更一般地理解它 ExecutorService service = new ThreadPoolExecutor(10, 10, 1000L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10,

在我的一个项目中使用ThreadPoolExecutor时,我开始从Java文档中阅读更多关于ThreadPoolExecutor的内容。有人能解释一下这条线的实际含义吗?-我知道每个参数代表什么,但我想从这里的一些专家那里更一般地理解它

ExecutorService service = new ThreadPoolExecutor(10, 10, 1000L,
TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10, true), new 
ThreadPoolExecutor.CallerRunsPolicy());
ExecutorService服务=新的线程池executor(10,10,1000L,
TimeUnit.millizes,新建ArrayBlockingQueue(10,true),新建
ThreadPoolExecutor.CallerRunPolicy());
更新:- 问题陈述是:-

每个线程使用1到1000之间的唯一ID,程序必须运行60分钟或更长时间,因此在这60分钟内,所有ID都可能完成,因此我需要再次重用这些ID。这是我用上面的执行器写的下面的程序

class IdPool {
    private final LinkedList<Integer> availableExistingIds = new LinkedList<Integer>();

    public IdPool() {
        for (int i = 1; i <= 1000; i++) {
            availableExistingIds.add(i);
        }
    }

    public synchronized Integer getExistingId() {
        return availableExistingIds.removeFirst();
    }

    public synchronized void releaseExistingId(Integer id) {
        availableExistingIds.add(id);
    }
}


class ThreadNewTask implements Runnable {
    private IdPool idPool;

    public ThreadNewTask(IdPool idPool) {
        this.idPool = idPool;
    }

    public void run() {
        Integer id = idPool.getExistingId();
        someMethod(id);
        idPool.releaseExistingId(id);
    }

// This method needs to be synchronized or not?
    private synchronized void someMethod(Integer id) {
        System.out.println("Task: " +id);
// and do other calcuations whatever you need to do in your program
    }
}

public class TestingPool {
    public static void main(String[] args) throws InterruptedException {
        int size = 10;
        int durationOfRun = 60;
        IdPool idPool = new IdPool();   
        // create thread pool with given size
        ExecutorService service = new ThreadPoolExecutor(size, size, 500L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(size), new ThreadPoolExecutor.CallerRunsPolicy()); 

        // queue some tasks
        long startTime = System.currentTimeMillis();
        long endTime = startTime + (durationOfRun * 60 * 1000L);

        // Running it for 60 minutes
        while(System.currentTimeMillis() <= endTime) {
            service.submit(new ThreadNewTask(idPool));
        }

        // wait for termination        
        service.shutdown();
        service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); 
    }
}
类IdPool{
private final LinkedList availableExistingIds=新LinkedList();
公共IdPool(){

对于(int i=1;i它正在创建一个
ExecutorService
,该服务处理线程池的执行。在这种情况下,池中的初始线程数和最大线程数都是10。当池中的线程空闲1秒(1000ms)时,它将杀死它(空闲计时器)但是,由于最大线程数和核心线程数相同,因此这种情况永远不会发生(它始终保持10个线程,并且运行的线程数永远不会超过10个)

它使用一个
ArrayBlockingQueue
来管理具有10个插槽的执行请求,因此当队列已满时(在10个线程排队后),它将阻止调用者


如果线程被拒绝(在这种情况下,这可能是由于服务关闭,因为线程将排队,或者如果队列已满,在排队线程时您将被阻止),那么提供的
Runnable
将在调用者的线程上执行。

[首先,我很抱歉,这是对先前答案的回应,但我想要格式化]

除实际情况外,当项目提交给具有完整队列的ThreadPoolExecutor时,您不会阻止。原因是ThreadPoolExecutor调用BlockingQueue.offer(T item)方法,根据定义,该方法是非阻止方法。它要么添加项目并返回true,要么不添加(完整时)然后ThreadPoolExecutor调用注册的RejectedExecutionHandler来处理这种情况

从javadoc:

在将来某个时候执行给定的任务。该任务可能会执行 在新线程或现有池线程中。如果无法 提交执行,因为该执行人已 关闭或由于已达到其容量,任务已被处理 由当前的RejectedExecutionHandler执行

默认情况下,使用ThreadPoolExecutor.AbortPolicy()从ThreadPoolExecutor的“submit”或“execute”方法抛出RejectedExecutionException

try {
   executorService.execute(new Runnable() { ... });
}
catch (RejectedExecutionException e) {
   // the queue is full, and you're using the AbortPolicy as the 
   // RejectedExecutionHandler
}
但是,您可以使用其他处理程序执行不同的操作,例如忽略错误(DiscardPolicy),或者在调用“execute”或“submit”方法(CallerRunPolicy)的线程中运行它。此示例允许调用“submit”或“execute”方法的线程在队列已满时运行请求的任务。(这意味着在任何给定时间,您都可以在池中的内容之上运行另外一个内容):

如果您想阻塞并等待,您可以实现自己的RejectedExecutionHandler,它将阻塞直到队列上有可用的插槽(这是一个粗略的估计,我没有编译或运行它,但您应该知道):


考虑信号量。这些都是为了同样的目的。请检查下面使用信号量的代码。不确定这是否是您想要的。但如果没有更多的许可证可以获取,这将阻止。ID对您也很重要吗

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

class ThreadNewTask implements Runnable {
    private Semaphore idPool;

    public ThreadNewTask(Semaphore idPool) {
        this.idPool = idPool;
    }

    public void run() {
//      Integer id = idPool.getExistingId();
        try {
            idPool.acquire();
            someMethod(0);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            idPool.release();
        }
//      idPool.releaseExistingId(id);
    }

    // This method needs to be synchronized or not?
    private void someMethod(Integer id) {
        System.out.println("Task: " + id);
        // and do other calcuations whatever you need to do in your program
    }
}

public class TestingPool {
    public static void main(String[] args) throws InterruptedException {
        int size = 10;
        int durationOfRun = 60;
        Semaphore idPool = new Semaphore(100); 
//      IdPool idPool = new IdPool();
        // create thread pool with given size
        ExecutorService service = new ThreadPoolExecutor(size, size, 500L,
                TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(size),
                new ThreadPoolExecutor.CallerRunsPolicy());

        // queue some tasks
        long startTime = System.currentTimeMillis();
        long endTime = startTime + (durationOfRun * 60 * 1000L);

        // Running it for 60 minutes
        while (System.currentTimeMillis() <= endTime) {
            service.submit(new ThreadNewTask(idPool));
        }

        // wait for termination
        service.shutdown();
        service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
    }
}
import java.util.concurrent.ArrayBlockingQueue;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Semaphore;
导入java.util.concurrent.ThreadPoolExecutor;
导入java.util.concurrent.TimeUnit;
类ThreadNewTask实现可运行{
专用信号量idPool;
公共线程任务(信号量idPool){
this.idPool=idPool;
}
公开募捐{
//整数id=idPool.getExistingId();
试一试{
idPool.acquire();
方法(0);
}捕捉(中断异常e){
e、 printStackTrace();
}最后{
idPool.release();
}
//idPool.releaseExistingId(id);
}
//此方法是否需要同步?
私有方法(整数id){
System.out.println(“任务:+id”);
//在你的程序中做任何你需要做的计算
}
}
公共类测试池{
公共静态void main(字符串[]args)引发InterruptedException{
int size=10;
int durationOfRun=60;
信号量idPool=新信号量(100);
//IdPool IdPool=新的IdPool();
//创建具有给定大小的线程池
ExecutorService服务=新的线程池Executor(大小,大小,500L,
TimeUnit.ms,新的ArrayBlockingQueue(大小),
新的ThreadPoolExecutor.CallerRunPolicy());
//将一些任务排队
long startTime=System.currentTimeMillis();
长结束时间=开始时间+(运行持续时间*60*1000L);
//运行60分钟

while(System.currentTimeMillis()另一个解决方案是对底层队列进行黑客攻击,将
offer
替换为
offer
,并使用较大的超时时间(最多292年,可以认为是无限的)


//辅助方法
私有静态布尔interruptbleInfiniteOffer(BlockingQueue q,Runnable r){
试一试{
返回q.offer(r,Long.MAX_值,TimeUnit.NANOSECONDS);//无限==292年
}捕捉(中断异常e){
返回false;
}
}
//具有阻塞的固定大小池(而不是o)
public class BlockUntilAvailableSlot implements RejectedExecutionHandler {
  public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
     if (e.isTerminated() || e.isShutdown()) {
        return;
     }

     boolean submitted = false;
     while (! submitted) {
       if (Thread.currentThread().isInterrupted()) {
            // be a good citizen and do something nice if we were interrupted
            // anywhere other than during the sleep method.
       }

       try {
          e.execute(r);
          submitted = true;
       }
       catch (RejectedExceptionException e) {
         try {
           // Sleep for a little bit, and try again.
           Thread.sleep(100L);
         }
         catch (InterruptedException e) {
           ; // do you care if someone called Thread.interrupt?
           // if so, do something nice here, and maybe just silently return.
         }
       }
     }
  }
}
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

class ThreadNewTask implements Runnable {
    private Semaphore idPool;

    public ThreadNewTask(Semaphore idPool) {
        this.idPool = idPool;
    }

    public void run() {
//      Integer id = idPool.getExistingId();
        try {
            idPool.acquire();
            someMethod(0);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            idPool.release();
        }
//      idPool.releaseExistingId(id);
    }

    // This method needs to be synchronized or not?
    private void someMethod(Integer id) {
        System.out.println("Task: " + id);
        // and do other calcuations whatever you need to do in your program
    }
}

public class TestingPool {
    public static void main(String[] args) throws InterruptedException {
        int size = 10;
        int durationOfRun = 60;
        Semaphore idPool = new Semaphore(100); 
//      IdPool idPool = new IdPool();
        // create thread pool with given size
        ExecutorService service = new ThreadPoolExecutor(size, size, 500L,
                TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(size),
                new ThreadPoolExecutor.CallerRunsPolicy());

        // queue some tasks
        long startTime = System.currentTimeMillis();
        long endTime = startTime + (durationOfRun * 60 * 1000L);

        // Running it for 60 minutes
        while (System.currentTimeMillis() <= endTime) {
            service.submit(new ThreadNewTask(idPool));
        }

        // wait for termination
        service.shutdown();
        service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
    }
}