java - ThreadPoolExecutor 仅运行第一个可运行对象

标签 java multithreading executorservice

我有一个线程池执行器

private ExecutorService exec=Executors.newCachedThreadPool();

我有课

class MyCallable implements Callable<String>{

    private ReentrantLock lock=new ReentrantLock();

    private Condition cond=lock.newCondition();


    public String call(){

    System.out.println("TEST!!);
    try{
      lock.lock();
      cond.await();
    }finally{
       lock.unlock();
    }
   }
}

我愿意:

for(int i=0;i<10000;i++){
   exec.submit(new MyCallable());
}

我想要 10000 个线程等待可调用,但我只能看到一个测试!在我的日志中,所以它只提交我的任务一次,为什么它卡住???我的可调用对象在每个对象实例中都有自己的锁,如何拥有 1000 个等待线程?

最佳答案

我获取了你的代码,填充了缺失的部分,修复了编译错误并运行了它。它打印“测试!!”很多次。如果我将任务数量减少到合理的数量,它就会运行到完成。如果我将其保留为 10,000,则测试会失败,并显示 OOME,表明它无法分配更多线程堆栈。

<小时/>

I want to have 10000 threads with waiting callables

我的测试表明,许多线程会导致内存不足。这真的、真的不是一个好主意。

<小时/>

这是我使用的确切代码:

package test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExecutorTest {

    public static void main(String[] args) {
        ExecutorService exec = Executors.newCachedThreadPool();
        for (int i = 0; i < 10000; i++) {
            exec.submit(new MyCallable());
        }
    }
}


package test;

import java.util.concurrent.Callable;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

class MyCallable implements Callable<String> {

    private ReentrantLock lock = new ReentrantLock();

    private Condition cond = lock.newCondition();

    public String call() {

        System.out.println("TEST!!");
        try {
            lock.lock();
            cond.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return "foo";
    }
}
<小时/>

这是 while(true) {await} 测试:

[steve@newbox ~]$ cat ./workspace/test/src/test/CondAwait.java 
package test;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class CondAwait {

    public static void main(String[] args) throws InterruptedException {
         ReentrantLock lock = new ReentrantLock();

         Condition cond = lock.newCondition();
         lock.lock();
         while(true){
             System.out.println("Hi!");
             cond.await();
         }
    }

}
[steve@newbox ~]$ java -cp ./workspace/test/bin test.CondAwait 
Hi!
^C[steve@newbox ~]$ 

简而言之,主线程在第一个 await 调用中卡住......正如我所料。

<小时/>

I agree that it`s not a good idea, but those threads will be like a request cache, user sends a request, it's processor should be put into the thread pool, if we have 10k requests per second, you will see 10k threads in the pool. Please suggest how to do it better.

使用有界线程池,并将界限设置为大致等于您拥有的核心数量。

当然,您不会同时暂停 10,000 个可调用项,但这是一件好事。

如果这些可调用对象旨在模拟等待几秒钟以等待外部响应的请求,那么最多 100 个线程池可能是合理的。但是,如果您确实需要大规模并行性,那么您应该考虑使用 NIO 选择器,以便少量工作线程可以运行大量请求,将它们交错而不是阻塞 I/O。

关于java - ThreadPoolExecutor 仅运行第一个可运行对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30482185/

相关文章:

java - 从调用方法并行执行方法

java - Intellij 13 在调试时不保存/编译

mysql - SQL 最后插入到 Drupal 中。它真的是线程安全的吗?

java - 并发框架中shutdownNow的使用

Java ExecutorService 任务生成

c# - 如何在 C# 中解决车辆跟踪 GPS 收集数据的最佳解决方案?

java - (Java使用eclipse)currentTimeMillis()

java - AES-256 可以在 API 级别 26+ 的 Android 设备上工作吗?

java - 如何在java中使用jscience常量?

c++ - C++中的线程间通信