对java的BitSet的多线程并发的探索

java的BitSet不是线程安全的,所以多线程的时候h要加锁。
1 直接加锁整个BitSet        用时:3.4秒 
2 BitSet拆成更小的粒度     用时:3.6秒
3 使用并发的BitSet,自己写了个AtomicBitSet   用时:3.3秒

从测试结果来看 性能都差不多
感觉有点疑惑,在我的想象中2还和3应该会比1好不少的啊

下面3个测试分别对应3种方式
附件是完整代码


测试1
package com.eyu.gift.service;

import java.util.BitSet;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

import org.junit.Test;

/**
 * 用时3.4秒
 * @author bean
 */
public class BitsetTest1 {
	public static final int NUM = 50000000;

	@Test
	public void mutiThreadTest() {
		BitSet bitset = new BitSet();
		ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(20);
		int total = NUM / 10;
		Random random = new Random(1234);
		for (int i = 1; i < total; i++) {
			int targrt = random.nextInt(NUM);
			if (targrt % 5 == 0) {
				executorService.execute(new Task1(bitset, i));
			} else {
				executorService.execute(new ReadBitTask1(bitset, i));
			}
		}
		executorService.shutdown();
		while (true) {
			if (executorService.isTerminated()) {
				break;
			}
		}
	}

}

class Task1 implements Runnable {
	private int id;
	private BitSet bitset;

	public Task1(BitSet bitset, int id) {
		this.bitset = bitset;
		this.id = id;
	}

	@Override
	public void run() {
		synchronized (bitset) {
			bitset.set(id);
		}

	}
}

class ReadBitTask1 implements Runnable {
	private int id;
	private BitSet bitset;

	public ReadBitTask1(BitSet bitset, int id) {
		this.bitset = bitset;
		this.id = id;
	}

	@Override
	public void run() {
		synchronized (bitset) {
			bitset.get(id);
		}

	}
}



测试2
package com.eyu.gift.service;

import java.util.BitSet;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

import org.junit.Test;

/**
 * 用时3.6秒
 * @author bean
 */
public class BitsetTest2 {
	public static final int NUM = 50000000;
	static Object[] locks;

	static {
		locks = new Object[10000];
		for (int i = 0; i < 10000; i++) {
			locks[i] = new Object();
		}
	}

	@Test
	public void mutiThreadTest() {
		BitSet bitset = new BitSet();
		ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(20);
		int total = NUM / 10;
		Random random = new Random(1234);
		for (int i = 1; i < total; i++) {
			int targrt = random.nextInt(NUM);
			if (targrt % 5 == 0) {
				executorService.execute(new Task2(bitset, i));
			} else {
				executorService.execute(new ReadTask2(bitset, i));
			}
		}
		executorService.shutdown();
		while (true) {
			if (executorService.isTerminated()) {
				break;
			}
		}
	}

	public static Object getLock(int i) {
		return locks[i % 10000];
	}

}

class Task2 implements Runnable {
	private int id;
	private BitSet bitset;

	public Task2(BitSet bitset, int id) {
		this.bitset = bitset;
		this.id = id;
	}

	@Override
	public void run() {
		Object lockObject = BitsetTest2.getLock(id);
		synchronized (lockObject) {
			bitset.set(id);
		}

	}
}

class ReadTask2 implements Runnable {
	private int id;
	private BitSet bitset;

	public ReadTask2(BitSet bitset, int id) {
		this.bitset = bitset;
		this.id = id;
	}

	@Override
	public void run() {
		Object lockObject = BitsetTest2.getLock(id);
		synchronized (lockObject) {
			bitset.get(id);
		}

	}
}



测试3

package com.eyu.gift.service;

import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

import org.junit.Test;

/**
 * 用时3.3秒
 * @author bean
 */
public class BitSetTest3 {

	public static final int NUM = 50000000;

	@Test
	public void mutiAtomThreadTest() {
		AtomicBitSet bitset = new AtomicBitSet(NUM);
		ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(20);
		int total = NUM / 10;
		Random random = new Random(1234);
		for (int i = 1; i < total; i++) {
			int targrt = random.nextInt(NUM);
			if (targrt % 5 == 0) {
				executorService.execute(new Task3(bitset, i));
			} else {
				executorService.execute(new ReadTask3(bitset, i));
			}
		}
		executorService.shutdown();
		while (true) {
			if (executorService.isTerminated()) {
				break;
			}
		}
	}

}

class Task3 implements Runnable {
	private int id;
	private AtomicBitSet bitset;

	public Task3(AtomicBitSet bitset, int id) {
		this.bitset = bitset;
		this.id = id;
	}

	@Override
	public void run() {
		bitset.set(id);

	}
}

class ReadTask3 implements Runnable {
	private int id;
	private AtomicBitSet bitset;

	public ReadTask3(AtomicBitSet bitset, int id) {
		this.bitset = bitset;
		this.id = id;
	}

	@Override
	public void run() {
		bitset.get(id);

	}
}



并发安全BitSet:
package com.eyu.gift.service;

import java.util.concurrent.atomic.AtomicIntegerArray;

public class AtomicBitSet {
    private final AtomicIntegerArray array;

    public AtomicBitSet(int length) {
        int intLength = (length + 31) / 32;
        array = new AtomicIntegerArray(intLength);
    }

    public void set(long n) {
        int bit = 1 << n;
        int idx = (int) (n >>> 5);
        while (true) {
            int num = array.get(idx);
            int num2 = num | bit;
            if (num == num2 || array.compareAndSet(idx, num, num2))
                return;
        }
    }

    public boolean get(long n) {
        int bit = 1 << n;
        int idx = (int) (n >>> 5);
        int num = array.get(idx);
        return (num & bit) != 0;
    }
}





你可能感兴趣的:(bitset)