ThreadPoolExecutor中的线程正在等待 - java

这段代码运行很慢。我转储了线程,几乎同时运行了一个线程,但是当我将ExecutorService更改为ForkJoinPool时,代码运行得非常快。我不知道为什么线程在等待,我的计算机有8个核心...

ThreadPoolExecutor中的线程正在等待 - java

public class Tests {

    public static void main(String[] args) throws InterruptedException {

        int NUM_OF_THREADS = 8;
        int NUM_OF_INCREMENTS = 100_000_000;
        //ExecutorService service = Executors.newWorkStealingPool();
        ExecutorService service = Executors.newFixedThreadPool(NUM_OF_THREADS);
        final Counter counter = new StupidCounter();

        long before = System.currentTimeMillis();
        for (int i = 0; i < NUM_OF_INCREMENTS; i++) {
            service.submit(newCounterClient(counter, i));
        }
        service.shutdown();
        service.awaitTermination(1, TimeUnit.MINUTES);
        long end = System.currentTimeMillis();
        System.out.println(end - before);
        System.out.println(counter.getCounter());
    }


    static class CounterClient implements Runnable {
        private Counter counter;
        private int num;

        public CounterClient(Counter counter, int num) {
            this.counter = counter;
            this.num = num;
        }

        @Override
        public void run() {
            counter.increment();
        }
    }

    static interface Counter {
        void increment();

        long getCounter();
    }

    static class StupidCounter implements Counter {
        long i = 0;

        @Override
        public void increment() {
            i++;
        }

        @Override
        public long getCounter() {
            return i;
        }
    }

}
"pool-1-thread-7" #17 prio=5 os_prio=31 tid=0x00007faaa481c000 nid=0x6503 waiting on condition [0x0000700001d6d000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x00000006c006b3d8> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:897)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
    at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
    at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:439)
    at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(617Thread.java:745)

参考方案

很难从该代码中得出任何真实的结论,因为它实际上并没有做任何事情。执行程序的内部队列是瓶颈,这就是为什么您一次只能看到1个线程在“工作”的原因。它实际上并没有工作,它正在从队列中获取下一个任务,使所有其他线程(也在获取下一个任务)处于等待状态。除了LinkedBlockingQueue.take()的功能之外,您实际上没有在这里进行任何测试。

increment()方法不是线程安全的,因此基本上您正在测试错误的代码,并且结果几乎无关紧要。如果您使CounterClient任务执行实际的工作,这需要花费数毫秒的时间,那么与ForkJoinPool相比,您会发现性能差异小得多(如果有)。

JAVA:字节码和二进制有什么区别? - java

java字节代码(已编译的语言,也称为目标代码)与机器代码(当前计算机的本机代码)之间有什么区别?我读过一些书,他们将字节码称为二进制指令,但我不知道为什么。 参考方案 字节码是独立于平台的,在Windows中运行的编译器编译的字节码仍将在linux / unix / mac中运行。机器代码是特定于平台的,如果在Windows x86中编译,则它将仅在Win…

java:继承 - java

有哪些替代继承的方法? java大神给出的解决方案 有效的Java:偏重于继承而不是继承。 (这实际上也来自“四人帮”)。他提出的理由是,如果扩展类未明确设计为继承,则继承会引起很多不正常的副作用。例如,对super.someMethod()的任何调用都可以引导您通过未知代码的意外路径。取而代之的是,持有对本来应该扩展的类的引用,然后委托给它。这是与Eric…

Java:BigInteger,如何通过OutputStream编写它 - java

我想将BigInteger写入文件。做这个的最好方式是什么。当然,我想从输入流中读取(使用程序,而不是人工)。我必须使用ObjectOutputStream还是有更好的方法?目的是使用尽可能少的字节。谢谢马丁 参考方案 Java序列化(ObjectOutputStream / ObjectInputStream)是将对象序列化为八位字节序列的一种通用方法。但…

Java-如何将此字符串转换为日期? - java

我从服务器收到此消息,我不明白T和Z的含义,2012-08-24T09:59:59Z将此字符串转换为Date对象的正确SimpleDateFormat模式是什么? java大神给出的解决方案 这是ISO 8601标准。您可以使用SimpleDateFormat simpleFormat = new SimpleDateFormat("yyyy-MM…

Java:从类中查找项目名称 - java

仅通过类的实例,如何使用Java反射或类似方法查找项目名称?如果不是,项目名称(我真正想要的是)可以找到程序包名称吗? 参考方案 项目只是IDE使用的简单组织工具,因此项目名称不是类或JVM中包含的信息。要获取软件包,请使用Class#getPackage()。然后,可以调用Package#getName()将包作为您在代码的包声明中看到的String来获取…