java - 如何避免同步和对象创建?

标签 java performance concurrency logic

  1. 我使用 JOGL 用 Ja​​va 编写了一个 OpenGL 应用程序。我试图完全避免在主应用程序阶段创建对象,因为这可能会导致 GC 造成的小周期性滞后。

  2. 我想用我自己的方法包装一些 JOGL 的方法。想象一下一个方法void method(int[] result, int offset),它接收指向数组的指针和一个偏移量,并将一个整数值放入其中的指定索引处。我想用简单的 int getResult()

  3. 包装它
  4. 所以我需要在某处创建一个临时数组,并且我必须提前这样做(根据 1)。

  5. 但是,如果它将存储在包含此包装器方法的类的字段中,这将迫使我使包装器方法同步。我知道大多数单线程访问的同步不会产生很大的开销,但我仍然想知道是否有更好的解决方案。

注释:

  • 同步不是答案,3.000.000个同步块(synchronized block),仅monitorenter-monitorexit需要17毫秒。如果你想保持 60 fps,你只有 16.(6)。

由于我没有足够的权力来投票,所以我发现欣赏 Dave 答案的唯一方法就是编写演示:

class Test {
    private static final int CYCLES = 1000000000;

    int[] global = new int[1];
    ThreadLocal<int[]> local = new ThreadLocal<int[]>();

                 void _fastButIncorrect() { global[0] = 1; }
    synchronized void _slowButCorrect()   { global[0] = 1; }

    void _amazing()   {
        int[] tmp = local.get();
        if( tmp == null ){
            tmp = new int[1];
            local.set(tmp);
        }
        tmp[0] = 1;
    }

    long fastButIncorrect() {
        long l = System.currentTimeMillis();
        for (int i = 0; i < CYCLES; i++) _fastButIncorrect();
        return System.currentTimeMillis() - l;
    }
    long slowButCorrect() {
        long l = System.currentTimeMillis();
        for (int i = 0; i < CYCLES; i++) _slowButCorrect();
        return System.currentTimeMillis() - l;
    }
    long amazing() {
        long l = System.currentTimeMillis();
        for (int i = 0; i < CYCLES; i++) _amazing();
        return System.currentTimeMillis() - l;
    }
    void test() {
        System.out.println(
                        "fastButIncorrect cold: " + fastButIncorrect() + "\n" +
                        "slowButCorrect   cold: " + slowButCorrect()   + "\n" +
                        "amazing          cold: " + amazing()          + "\n" +
                        "fastButIncorrect  hot: " + fastButIncorrect() + "\n" +
                        "slowButCorrect    hot: " + slowButCorrect()   + "\n" +
                        "amazing           hot: " + amazing()          + "\n"
        );
    }
    public static void main(String[] args) {
        new Test().test();
    }
}

在我的机器上结果是:

fastButIncorrect cold: 40
slowButCorrect   cold: 8871
amazing          cold: 46
fastButIncorrect  hot: 38
slowButCorrect    hot: 9165
amazing           hot: 41

再次感谢戴夫!

最佳答案

如果你没有太多线程,你可以使用ThreadLocal:

ThreadLocal<int[]> tmpArrayThreadLocal = new ThreadLocal<int[]>();

使用此代码:

int[] tmpArray = tmpArrayThreadLocal.get();
if( tmpArray == null ){
   tmpArray = new int[100];
   tmpArrayThreadLocal.set(tmpArray);
}
method(tmpArray, 5)

您可以通过将 ThreadLocal 封装在另一个类中来清理代码。

关于java - 如何避免同步和对象创建?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19868576/

相关文章:

java - 使用 sharedpreferences 保存一个数组列表并在 ListView 中显示

java - 为什么以及如何避免 Maven 在 mvn 包上的 jsp 中替换 ${id}

java - 滑动浏览图像的 UI

java - Java 中的数组数组

java - JVM 性能测试套件

performance - 为什么 Raku 在使用多维数组时表现如此糟糕?

java - GSON 序列化非常非常慢

java - 信号量和条件的区别(ReentrantLock)

java - 原子比较和交换是否可以在看不到惰性写入的情况下覆盖它?

multithreading - 如何使并发与写入 hive 表的数据帧一起工作?