Java中的高优先级线程

时间:2012-08-09 17:25:21

标签: java multithreading scheduling

我目前正致力于分布式应用程序的性能。我的目标是网络组件。目前,对于每个连接,都有一个专用线程,它以阻塞模式处理套接字。我的目标是减少线程数量(不降低性能),并尽可能提高性能。

我重新设计了网络组件以使用异步通信,并尝试使用1到2个线程进行整个网络处理。我做了一个简单的测试,我在一个循环中写入一个节点并在另一个节点上读取,这是为了测试max nw线程功能,我发现我的繁忙循环实现消耗100%cpu并且每秒获得更多操作然后我们要求。所以我将这个繁忙的循环实现集成到现有的应用程序中。

问题我发现其他线程不允许这些异步nw线程获取完整的cpu,即使我有一个8核系统而且我们没有使用超过400%的cpu。基本上是一个C程序员我会通过在核心上绑定我的nw线程并提高其调度优先级来解决这个问题,这样其他线程仍然可以在其他核心上运行。我无法在Java中做类似的事情。 Java线程优先级存在冲突的评论。此外,我不想降低其他线程的优先级,因为它可能有其自身的副作用。

你会如何解决这个问题?

2 个答案:

答案 0 :(得分:3)

我有一个库在Linux和Windows上支持Java中的线程关联。 https://github.com/peter-lawrey/Java-Thread-Affinity

如果你隔离了CPU,你可以确保你指定的CPU不会用于其他任何东西(不可屏蔽的中断除外)这在Linux AFAIK中效果最好。


如果您使用非阻塞NIO忙于等待而不是阻止IO,则可以获得较低的延迟结果。后者在负载下工作效果最好,在负载较低时,延迟会增加。

您可能会发现此库感兴趣https://github.com/peter-lawrey/Java-Chronicle它允许您每秒持续存储数百万条消息,可选择再保存到第二个进程。

顺便说一句:线程优先级只是一个提示,操作系统可以自由地忽略它(通常会)


比较热代码和冷代码的简单示例。它所做的就是重复复制一个数组并计时。一旦代码和数据变暖,你就不会期望它变慢,但即使在相当机器上也需要10毫秒的延迟才能减慢显着复制所需的时间。

public static void main(String... args) throws InterruptedException {
    int[] from = new int[60000], to = new int[60000];
    for (int i = 0; i < 10; i++)
        copy(from, to); // warm up
    for (int i = 0; i < 10; i++) {
        long start = System.nanoTime();
        copy(from, to);
        long time = System.nanoTime() - start;
        System.out.printf("Warm copy %,d us%n", time / 1000);
    }
    for (int i = 0; i < 10; i++) {
        Thread.sleep(10);
        long start = System.nanoTime();
        copy(from, to);
        long time = System.nanoTime() - start;
        System.out.printf("Cold copy %,d us%n", time / 1000);
    }
}

private static void copy(int[] a, int[] b) {
    for (int i = 0, len = a.length; i < len; i++)
        b[i] = a[i];
}

打印

Warm copy 20 us
Warm copy 20 us
Warm copy 19 us
Warm copy 23 us
Warm copy 20 us
Warm copy 20 us
Cold copy 100 us
Cold copy 80 us
Cold copy 89 us
Cold copy 92 us
Cold copy 80 us
Cold copy 112 us

答案 1 :(得分:1)

这真的让我过早优化。你有一个8核系统,只使用400%的CPU。是什么让你认为这不是IO绑定程序的教科书范例?是什么让您认为您没有超出您的网络IO链?

@Peter知道他的东西,我确信你可以破解处理器亲和力并强制你的关键线程到一个CPU,但问题是它会让你的程序运行得更快吗?我真诚地怀疑它。关于线程调度,模型Java VM 非常智能,我建议它正在适当地完成它的工作。除非你有相反的非常好的证据,否则我会让它处理调度。如果大多数线程都在等待IO,那么即使优先级也很少。

此外,是什么让你认为减少线程数在某种程度上更好。这将大量代码从本地(即线程多路复用)移动到Java域(即NIO代码)。如果你在讨论1000个线程,那么我同意,但即使是100个线程也应该是处理连接的有效方法。

我已经完成了大量的线程编程超过二十年,而且我从未必须强制线程亲和力。当然,调整线程池并确定应用线程池与专用线程的位置的良好决策是一门艺术,但迫使VM按照您认为的方式安排线程并不能很好地利用您的时间。花了一些时间与一个分析器找出你的程序花费的时间将是一个更好的投资恕我直言。