【发布时间】:2018-08-16 15:37:24
【问题描述】:
我有一个多线程 Java 应用程序,它使用多个 CPU 密集型线程来收集信息。每隔几分钟,就会发现一个需要由程序的另一个线程处理的结果。找到的结果被添加到列表中,并通知其他相关线程(使用锁和条件),然后处理找到的信息。我需要将这些信息从线程传递到线程的时间延迟尽可能小。在使用 System.currentTimeMillis() 测量唤醒和通知之间的时间时,延迟通常小于 5 毫秒,并且通常小于或等于 1 毫秒。有时,延迟更大(10-20ms)。由于毫秒是计算机的宏单位,我认为可靠地小于 1 毫秒的延迟应该是可能的,这将有利于我的应用程序。
您是否知道造成较大延迟的原因是什么,或者我如何才能找到查看的位置?会不会是垃圾收集?或者线程唤醒的几毫秒变化被认为是正常的?
我在 Linux Ubuntu 虚拟专用服务器上使用 Java 版本 1.8.0。
附上一个程序设计的例子。运行它并不能正确模拟我的生产程序观察到的延迟。 “实际”程序使用大量内存、CPU,并且每隔几分钟只传输一次信息。我尝试过,但未能简单地模拟这个。
谢谢。
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.Condition;
import java.util.List;
import java.util.ArrayList;
import java.util.Random;
public class Example {
public static void main(String[] args) {
startInfoThreads();
startWatcherThread();
}
private static Lock lock = new ReentrantLock();
private static Condition condition = lock.newCondition();
private static List<Long> infoList = new ArrayList<>();
private static void startWatcherThread () {
Thread t = new Thread () {
@Override
public void run () {
while (true) {
// Waiting for results...
try {
lock.lock();
while (infoList.size() == 0) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
long delta = System.currentTimeMillis() - infoList.remove(0);
if (delta > 0)
System.out.println("Time for waking up: " + delta);
} finally {
lock.unlock();
}
// Do something with info
}
}
};
t.start();
}
private static void startInfoThreads () {
for (int i = 0; i < 14; i++) {
Thread t = new Thread() {
@Override
public void run() {
Random r = new Random();
while (true) {
// Gather info, 'hits' about once every few minutes!
boolean infoRandomlyFound = r.nextInt(100) >= 99;
if (infoRandomlyFound) {
try {
lock.lock();
infoList.add(System.currentTimeMillis());
condition.signal();
} finally {
lock.unlock();
}
}
}
}
};
t.start();
}
}
}
【问题讨论】:
-
查看这篇标题为The slow currentTimeMillis() 的非常详细的文章。我想作者是为你写的!作为一个单独的问题,您可以更新您的问题以指定您的 Java 版本和操作系统。
-
您的设置有多少个内核以及创建/执行了多少个线程?
-
8 核心设置。大约 11 个线程正在“猛烈”地收集信息,而另一个线程正在闲置等待信息到达。升级到 16 核设置可能是合适的,但对我目前的主机来说相当昂贵。
-
代码太多,无法做出突出问题的连贯演示,所以我认为显示一些代码不会有帮助。
-
@Jeroen Re "代码太多了" => 是否可以创建 MCVE?见How to create a Minimal, Complete, and Verifiable example
标签: java multithreading