今天面试阿里被问到一个简单的多线程问题,脑子里第一个闪现的是wait()和notify(),写代码的时候又蹦出些其它想法,结果写的时间有点长,实现也有点混乱,回来后把当时的想法整理了一下,分别比较一下实现效率。
1.synchronized + wait +notify
这个实现可以看连接https://blog.csdn.net/woainiwss/article/details/52013810
2.condition + await + signal
private static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();private static Condition condition = lock.writeLock().newCondition();private static final void runCount(Boolean ood) throws InterruptedException { for (int i = 0; i<100001;i++) {lock.writeLock().lock();if(ood){if(i%2==1){//System.out.println(i);condition.await();continue; }else{condition.signal(); } }else{if(i%2==0){//System.out.println(i);condition.await();continue; }else{condition.signal(); } }lock.writeLock().unlock();if(i==100000){System.out.println(System.currentTimeMillis()); } }}
3.AtomicInteger + while循环
private static volatile AtomicInteger count = new AtomicInteger(0);
private static final void spinCount(Boolean odd ){
while (true){
if(odd && count.get()%2 == 0){
//System.out.println(count.get());
if(count.incrementAndGet() == 100001){
System.out.println(System.currentTimeMillis());
return;
}
}else if(!odd && count.get()%2 == 1){
//System.out.println(count.get());
count.incrementAndGet();
}
}
}
最后调用
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
runCount(false);
//spinCount(false);
//syncCount1();
} catch (Exception e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
runCount(true);
//spinCount(true);
//syncCount2();
} catch (Exception e) {
e.printStackTrace();
}
}
});
System.out.println(System.currentTimeMillis());
t1.start();
t2.start();
}
循环次数小的情况下效率上 第一种>第二种>第三种。
在循环次数较少的时候JDK自己控制的synchronized关键字效率最高,看起来无锁化的第三种反而效率最低。 第二种用condition实现的代码会优雅些,但是效率差一点点。另外我直接把第二种的代码换成synchronized来实现的话,次数稍微多点就会出现死锁,说明新的juc对锁的控制上要更好点。
循环次数大的情况下效率上 第三种 > 第一种 > 第二种。
随着次数增加 前两种加锁的要比循环的消耗时间增长的快。在10W次的时候,第一种550ms,第二种605ms,而第三种只需要25ms,效率差距明显
这三种只是我的一点拙见,希望能抛砖引玉,有谁能提供更好的思路,谢谢
网友评论