Java如何限制作用于方法的线程数

Posted

技术标签:

【中文标题】Java如何限制作用于方法的线程数【英文标题】:Java how to limit number of threads acting on method 【发布时间】:2015-06-15 08:43:57 【问题描述】:

我的 Web 应用程序中有 java 方法执行繁重的文件操作。问题是,如果超过 5 个线程同时出现(这将进入测试阶段),它就会崩溃。我的意思是它无法处理繁忙的交通。

这就是为什么我想一次处理最多 5 个请求的方法,如果第 6 个请求到来,它将等到前 5 个请求中的一个完成

public  synchronized void add(int value)
      File a=new File("D:/heavyFile1");
      File b=new File("D:/heavyFile2");
      File c=new File("D:/heavyFile3");
      //operation on file
  

我添加了同步关键字,但它一次只处理一个请求,导致性能问题,因为每个下一个线程都必须等到它完成。请帮帮我。

【问题讨论】:

我看不出这段代码与你的问题有什么关系。 【参考方案1】:

您可以在执行逻辑内部使用Executor.newFixedThreadPool 成语。

下面的完整示例:

public class Main 

    public static void main(String[] args) throws Exception 
        Main m = new Main();
        // simulating a window of time where your method is invoked continuously
        for (int i = 0; i < 11; i++) 
            m.doSomething();
        
        // shutting down executor when done
        m.terminate();
    

    ExecutorService executor = Executors.newFixedThreadPool(5);

    // internally submits a new task to the executor
    public void doSomething() 
        executor.submit(new Runnable() 
            @Override
            public void run() 
                long wait = ThreadLocalRandom.current().nextLong(2000);
                try 
                    System.out.printf(
                        "%s is sleeping for %dms.%n", 
                        Thread.currentThread().getName(), 
                        wait
                    );
                    Thread.sleep(wait);
                
                catch (InterruptedException ie) 
                    // suppressed
                
                System.out.printf(
                    "%s is doing something!%n", 
                    Thread.currentThread().getName()
                );
            
        );
    

    public void terminate() throws Exception 
        executor.shutdown();
    

输出

会有所不同,具体如下:

pool-1-thread-1 is sleeping for 1533ms.
pool-1-thread-4 is sleeping for 784ms.
pool-1-thread-3 is sleeping for 684ms.
pool-1-thread-5 is sleeping for 1375ms.
pool-1-thread-2 is sleeping for 1717ms.
pool-1-thread-3 is doing something!
pool-1-thread-3 is sleeping for 1252ms.
pool-1-thread-4 is doing something!
pool-1-thread-4 is sleeping for 301ms.
pool-1-thread-4 is doing something!
pool-1-thread-4 is sleeping for 1140ms.
pool-1-thread-5 is doing something!
pool-1-thread-5 is sleeping for 1454ms.
pool-1-thread-1 is doing something!
pool-1-thread-1 is sleeping for 1594ms.
pool-1-thread-2 is doing something!
pool-1-thread-2 is sleeping for 227ms.
pool-1-thread-3 is doing something!
pool-1-thread-2 is doing something!
pool-1-thread-4 is doing something!
pool-1-thread-5 is doing something!
pool-1-thread-1 is doing something!

注意

查看重复使用的线程名称,这些是新提交的任务,在池中分配了一个空闲线程。

【讨论】:

谢谢@Mena 看起来你的解决方案对我有用。【参考方案2】:

您可以创建一个Executor,并使用Semaphore 限制它接受的任务数量。像这样的:

private final Semaphore semaphore = new Semaphore(4);
ThreadPoolExecutor tp= new ThreadPoolExecutor(...)
      public void execute(Runnable r)
          semaphore.acquire();
          super.execute(r);
          
      public void afterExecute(Runnable r, Thread t)
         semaphore.release();  
         super.afterExecute(r,t);
      
;

【讨论】:

Adam,如果你能给我样例程序,我会很兴奋,因为我对此一无所知 我不是来写程序的,而是来写答案的。您的工作是进行研究并使用用户在此处给出的指示。建议大家阅读Oracle官方文档的并发轨迹:trail【参考方案3】:

信号量。在里面。有 5 个单元,让线程在函数顶部等待,最后发出信号。

【讨论】:

能否提供代码,因为我不知道【参考方案4】:

您可以使用 ThreadPool 并限制为 5 个线程。在此,您创建一个 ThreadPool 并向其提交一个新线程以用于您的课程。它只允许您配置的最大线程数同时工作。如果出现的线程数超过了配置的数量,它们将不得不等到某个工作线程完成它的任务。

一个例子:http://www.javacodegeeks.com/2013/01/java-thread-pool-example-using-executors-and-threadpoolexecutor.html

【讨论】:

【参考方案5】:

创建一个具有固定大小的thread pool 来执行此操作。

【讨论】:

以上是关于Java如何限制作用于方法的线程数的主要内容,如果未能解决你的问题,请参考以下文章

如何有效控制 Go 线程数?

linux线程数限制与zabbix监控

如何限制perl中的最大并行线程数

使用 Task.Run() 时如何限制最大线程数?

Java 线程数过多会造成什么异常?

Java并发工具类控制并发线程数的Semaphore