Search code examples
javajava-streamjava.util.concurrent

Avoiding usage of two AtomicInteger in a loop Java


I wish to read/write an array (and update another one) with a parallelStream, without an index.

AtomicInteger doesn't allow bitwise operations, and using j.get() * 2 is slow:

final int[] j = {0};
ps.parallelStream().forEach(p -> {
    long k = next[j[0] << 1];                       
    for(; k < finalK; k += p)
        seg[(int) (k >>> S)] |= (1L << (k & BMASK));
    next[j[0] << 1] = (k - finalK);

    k = next[j[0] << 1 | 1];                        
    for(; k < finalK; k+= p) 
        seg[(int) (k >>> S)] |= (1L << (k & BMASK));
    next[j[0] << 1 | 1] = (k - finalK);
    j[0]++;
});

This is working in a sequential stream, not in parallel.

Sorry, if the seg[(int) (k >>> S)] |= (1L << (k & BMASK));seems unreadable, it's just the same as setting the bit k of a BitSet(seg is a long[]), wich is too much slow for my purpose.


Solution

  • Resolved using an ugly ConcurrentHashMap<Long, Long[]> wich avoid the index

    next.replaceAll((p, k)->{
    
        for(; k[0] < finalK; k[0] += p)
            seg[(int) (k[0] >>> S)] |= (1L << (k[0] & BMASK));
    
        for(; k[1] < finalK; k[1] += p)                         
            seg[(int) (k[1] >>> S)] |= (1L << (k[1] & BMASK));
    
        return new long[]{k[0]-finalK, k[1]-finalK});
    });
    

    but this is very slow, and use much more memory

    EDIT
    I improved things using a little indexPairs class instead the array and a BitSet for clarity

    ConcurrentHashMap<Long, indexPairs> next = initNext();
    BitSet segment = new BitSet();
    while(condition) {
        next.replaceAll((p, k) -> {
            for (; k.low < finalK; k.low += p)
                segment.set(k.low);
            k.low -= finalK;
            for (; k.high < finalK; k.high += p)                 
                segment.set(k.high);
            k.high -= finalK;
            return k;
        });
        ... Do something with segment
    }