关于AtomicInteger变量的一些疑问

本人最近写了一段代码,用到了AtomicInteger对这个变量,但是期待的结果与代码的实际运行
结果相差好大,现将代码奉上,求各位大牛给下解决方案。
class IDGeneration {
private final static ConcurrentHashMap idMap = new ConcurrentHashMap();

    private static final long baseTime = 1462377600000L;
    private Lock lock;

    IDGeneration() {
        lock = new ReentrantLock();
    }

    @SuppressWarnings("unused")
    public Long generateRelativeIncrementUniqueId(String flag) {
        String dateString = GengratedUnqueId.formatDate(new Date(),
                GengratedUnqueId.PATTERN);
        Long currentTime = (System.currentTimeMillis() - baseTime);
        AtomicInteger queueId = new AtomicInteger(0);
        int i = 0;
        Long tempValue = null;
        lock.lock();
        try {
            queueId = idMap.get(currentTime);
            if (queueId == null) {
                queueId = new AtomicInteger(0);
                idMap.clear();
                idMap.put(currentTime, queueId);
                tempValue = (currentTime << 5 | queueId.get());
            } else {
                queueId.getAndIncrement();
                idMap.put(currentTime, queueId);
                tempValue = (currentTime << 5 | queueId.get());
            }
        } finally {
            lock.unlock();
        }
        return tempValue;
        return null;
    }
}


这是测试代码:
public static void main(String[] args) throws Exception {
static ConcurrentHashMap<Long, String> map = new ConcurrentHashMap<Long, String>();

    final IDGeneration idGeneration = new IDGeneration();
    for (int i = 0; i < 100; i++) {

        Thread thread = new Thread(new Runnable() {

            @Override
            public void run() {

                long value = idGeneration
                        .generateRelativeIncrementUniqueId();
                map.put(value, "");
            }
        });
        thread.start();

    }
    TimeUnit.SECONDS.sleep(5);
    System.out.println("map.size===" + map.size());
    }

5个回答

先说最早的版本:
// idMap.clear();
这行代码注释掉就可以了,少的部分其实是被你自己清除了,同步上是够了;

后面你改的,缺少同步,多线程不安全,改如下:

 public Long generateRelativeIncrementUniqueId() {
        long tempValue = (System.currentTimeMillis() - baseTime);
        long value = 0;
        AtomicInteger queueId = map.get(tempValue);
        if (queueId == null) {
            // 这里需要同步,因为map中还没有queueId
            synchronized (this) {
                // 需要再检验一遍
                queueId = map.get(tempValue);
                if (queueId == null) {
                    queueId = new AtomicInteger(0);
                    map.put(tempValue, queueId);
                }
            }
            value = (tempValue << 8 | queueId.getAndIncrement());
        } else {
            // queueId.getAndIncrement();
            // map.put(tempValue, queueId);//没必要
            value = (tempValue << 8 | queueId.getAndIncrement());
        }
        System.out.println(tempValue + "," + queueId.get());
        return value;
    }
u011606457
_1_1_7_ 你这问题有悬赏分吗?没看到,不过没关系,我也是涨见闻来的
接近 4 年之前 回复
lcx_1989210
lcx_1989210 谢谢你了,你的这个方案采纳了。是不是分就给你了呢?
接近 4 年之前 回复

逻辑就很大问题,全局变量和局部变量也没划分清楚,
特别: Long currentTime = (System.currentTimeMillis() - baseTime);
这个时间基本每次都不一样了,还需要缓存在idMap吗?

u011606457
_1_1_7_ ReentrantLock,ConcurrentHashMap在这里都是画蛇添足,且用法不当,导致了该问题
接近 4 年之前 回复
u011606457
_1_1_7_ 回复lcx_1989210: 是有问题,但不是AtomicInteger的问题,是你用法的问题
接近 4 年之前 回复
lcx_1989210
lcx_1989210 回复_1_1_7_: 不是吧,我这边用了AtomicInteger后,在currentTime一样的情况下,打印出的queueId还是会有重复的呢。
接近 4 年之前 回复
u011606457
_1_1_7_ 回复lcx_1989210: 你把问题复杂化,引来了不必要的麻烦和问题,AtomicInteger本身就可以保持原子性,多线程安全;代码我是运行过的,所以才那样评价的
接近 4 年之前 回复
lcx_1989210
lcx_1989210 这段代码最好运行一下,现在的问题就是currentTime的值一样,queueId在并发的情况下也会有重复。也就是说在毫秒级别内也有重复数据,现在就想解决这个重复数据的问题。现在加了lock锁的时候还是不行。
接近 4 年之前 回复

我简化了代码:

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class SimpleID {

private static final long baseTime = 1462377600000L;

public static void main(String[] args) throws Exception {
    final ConcurrentHashMap<Long, String> map = new ConcurrentHashMap<Long, String>();

    final SimpleID idGeneration = new SimpleID();
    for (int i = 0; i < 100; i++) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                long value = idGeneration.generateRelativeIncrementUniqueId();
                map.put(value, "");
            }
        });
        thread.start();

    }
    TimeUnit.SECONDS.sleep(5);
    System.out.println("map.size===" + map.size());
}

private AtomicInteger queueId = new AtomicInteger(0);

public Long generateRelativeIncrementUniqueId() {
    Long tempValue = baseTime + queueId.getAndIncrement();
    return tempValue;
}

}


AtomicInteger足够了,它本身是没问题的,这样你就可以好好理解AtomicInteger了

lcx_1989210
lcx_1989210 你这个方法我本地刚跑过了,你这样的测试确实没问题的。但是我现在很疑问的就是为什么加上if的一些逻辑之后就变得不可预见了,我在你这个基础上改了下代码,测试结果还是会有queueId重复的情况。
接近 4 年之前 回复

public Long generateRelativeIncrementUniqueId() {
long tempValue = (System.currentTimeMillis() - baseTime);
long value = 0;
queueId = map.get(tempValue);
if (queueId == null) {
queueId = new AtomicInteger(0);
map.put(tempValue, queueId);
value = (tempValue << 8 | queueId.get());
} else {
queueId.getAndIncrement();
map.put(tempValue, queueId);
value = (tempValue << 8 | queueId.get());
}
System.out.println(tempValue + "," + queueId.get());
return value;
}

这是处理方法的逻辑,main方法保持不变。运行结果后:map.size===95
下边的图片是几个重复的queueId的值。

![图片说明](https://img-ask.csdn.net/upload/201606/28/1467085304_869998.png)
lcx_1989210
lcx_1989210 我现在特别纳闷的就是为什么queueId会重复呢??
接近 4 年之前 回复

这是图片的部分重复数据的内容:
4707077338,0
4707077338,0
4707077338,2
4707077338,1
4707077339,0
4707077339,2
4707077339,2

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
关于AtomicInteger多线程中自增重复的问题

如图,代码如下,运行结果有重复![图片说明](https://img-ask.csdn.net/upload/201907/21/1563712444_209723.png) ![图片说明](https://img-ask.csdn.net/upload/201907/21/1563712470_213788.png) 代码红框区域改为下图,不在重复,想请问一下各位这是什么原因呢,应该怎么分析思考呢?![图片说明](https://img-ask.csdn.net/upload/201907/21/1563712572_310157.png)![图片说明](https://img-ask.csdn.net/upload/201907/21/1563712585_199988.png) 非常感谢

AtomicInteger真的支持并发操作吗?

JDK1.5中新增类AtomicInteger,支持免锁方式(原子方式)的更新Int的类,声明是线程安全的。我写了一个简单测试类,两个线程同时更新一个AtomicInteger,运行结果却和期望不一致,是否是程序写的有问题,还是AtomicInteger有问题? [code="java"]import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; public class TestVolatile { public static void main(String[] args) { for (int i = 0; i < 10; i++) { ExecutorService exe = Executors.newCachedThreadPool(); exe.execute(new VAddThead()); exe.execute(new VAddThead()); exe.shutdown(); while (!exe.isTerminated()) ; System.out.println(Bean.getInstance().getI()); } } } class VAddThead implements Runnable { @Override public void run() { for (int i = 0; i < 100; i++) { Bean.getInstance().addI(); } } } class Bean { private static Bean b = null; private volatile AtomicInteger i = new AtomicInteger(0); private Bean() { } public static Bean getInstance() { return b == null ? b = new Bean() : b; } public void addI() { i.getAndIncrement(); } public int getI() { return i.get(); } }[/code] 期望运行结果: [code="java"]200 400 600 800 1000 1200 1400 1600 1800 2000 [/code] 实际多次运行的结果都不一样,是何原因?本机的环境是JDK1.6.0_13,在windows和linux下测试都不正确。

java 多线程之 AtomicInteger问题

刚开始了解java.util.concurrent包下面的类,今天实验了一下,感觉AtomicInteger也没有保证 线程安全啊,代码如下: import java.util.concurrent.atomic.AtomicInteger; public class Test { private AtomicInteger cnt = new AtomicInteger(0); public void add() { cnt.incrementAndGet(); } public static void main(String[] args) { final Test test = new Test(); for (int i = 0; i < 10000; i++) { Thread a = new Thread(new Runnable() { public void run() { test.add(); } }); a.start(); } System.out.println(test.cnt); } } 输入结果:9996 多次试验,结果不定。9990~10000。不是说这个类的操作是线程安全的吗。是我用错了?

AtomicInteger:getAndIncrement()的实现原理求解

``` public final int getAndIncrement() { for (;;) { int current = get(); int next = current + 1; if (compareAndSet(current, next)) return current; } } public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); } ``` 书上说: 源码中for循环体的第一步先取得AtomicInteger里存储的数值,第二步对AtomicInteger的当前数值进行加1操作,关键的第三步调用compareAndSet方法来进行原子更新操作,该操作先检查当前数值是否等于current,等于意味着AtomicInteger的值没有被其他线程修改过,则将AtomicInteger的当前数值更新成next的值,如果不等compareAndSet方法会返回false,程序会进入for循环重新进行compareAndSet操作。 ----------------------------------------------------------------------------------- 我的疑问: 如果已经被其他线程修改过,此时再执行for()循环有什么意义呢?预期将3变成4,可谁知这时候被其他线程改成5了,不满足compareAndSet,此时重新进去for()循环又能怎么样呢?费解

Java AtomicInteger incrementAndGet也会存在线程不安全情况

public final int incrementAndGet() { for (;;) { int current = get(); int next = current + 1; if (compareAndSet(current, next)) return next; } } 以上是AtomicInteger的源码,使用自旋CAS的方式保证在最新值上修改。但是如果程序在compareAndSet以后,return之前其他线程执行了int next = current + 1;那么返回的值不一样不是我想要的吗? 例如:一开始的值是1,自旋加1以后应该返回2,但在更新值以后、return之前另外一个线程执行了int next = current + 1;那么返回的值不就是3了吗???

AtomicInteger 的CAS 问题

public final int incrementAndGet() { for (;;) { int current = get(); int next = current + 1; if (compareAndSet(current, next)) return next; } } 这是自增操作,定义: CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做 预期值是next吗? 内存值是current? 假如1个线程自增时没有其他线程竞争,那么预期值应该比内存值大1啊,怎么会预期值和内存值相同?

Java中关于原子变量和多线程安全问题

自学java碰到些问题,向各位大佬们请教下 多线程安全问题产生的前提 是不是 多线程对共享数据进行了非原子操作 既然是共享数据进行非原子性操作的化,那用AtomicXxx类应该能解决吧 但是.... ``` package Thread_01; import java.util.concurrent.atomic.AtomicInteger; class TicketSale2 implements Runnable{ //private int tickets=100; AtomicInteger tickets=new AtomicInteger(10); Object object=new Object(); //线程任务为售票,所以将该任务在run方法中执行 public void run(){ while(true) { //synchronized (object) { if(tickets.get()>0) { try { Thread.sleep(20); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"您好,您的票号为"+tickets.getAndDecrement()); } else{break;} //} } } } public class TicketDemo3 { public static void main(String[] args) { //线程任务对象 TicketSale2 ticketSale=new TicketSale2(); //线程对象 Thread t1=new Thread(ticketSale); Thread t2=new Thread(ticketSale); Thread t3=new Thread(ticketSale); Thread t4=new Thread(ticketSale); t1.start(); t2.start(); t3.start(); t4.start(); } } ``` 还是会产生线程安全问题...这是为什么呢 还望大佬们抽空解答下 ![图片说明](https://img-ask.csdn.net/upload/201901/12/1547275181_286997.png)

AutoInteger和automicInteger和atomicInteger有什么区别

AutoInteger和automicInteger和atomicInteger有什么区别? 为什么这三种叫法呀,是不是同一个东西呢? 路过的大佬们看下。谢谢啦 ![图片说明](https://img-ask.csdn.net/upload/201905/20/1558345188_35257.jpg)

关于synchronized的问题.

此为 thinking in java 的一个例子. 如果一个线程类,在run方法里掉一个方法r(),对一个 int i 的变量做两次自加操作 , 有一个方法叫 getValue() , 取得int i的值. main方法里,启动线程,同时一个死循环,一直取getValue(); 如果getValue()取得的值是奇数则退出. 当对方法r()做 synchronized的时候,是会取得奇数的, 当且并当 getValue() 做 synchronized时,就取不到奇数了. 个人理解的 synchronized是监视器只能当前线程在执行synchronized的方法.(蹩脚的个人描述,但同网上的一个理解) 假定 A 为自增线程 ,B 为main线程. 猜测:情况 r()为 synchronized , getValue() 不为synchronized, A自增了1次,切换到线程B,此时会取得奇数. 那么 synchronized 的方法执行时也是可以轮询到其他的线程的,这貌似也不违反并发的原则.因为另外一个线程并未执行此方法. 那为什么将 getValue() 设为 synchronized 时,就不会出现奇数的情况了呢? 帖代码: [code="java"] import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; public class AtomicIntegerTest implements Runnable { private AtomicInteger ai = new AtomicInteger(0); private Integer i = 0; @Override public void run() { // this.ai.addAndGet(2); r(); } private synchronized void r(){ while (true) { this.i++; this.i++; } } public synchronized int getValue() { // return ai.get(); return i; } public static void main(String[] args) { ExecutorService es = Executors.newCachedThreadPool(); final AtomicIntegerTest ai = new AtomicIntegerTest(); es.execute(ai); new Timer().schedule(new TimerTask() { @Override public void run() { System.out.println("close"); //System.out.println(ai.getValue()); System.exit(0); } }, 5000); int i; while (true) { i = ai.getValue(); System.out.println("-" + i); if (i % 2 != 0) { System.out.println("--" + i); System.exit(0); } Thread.yield(); } } } [/code]

Java调用Thread.sleep()方法的神奇问题

写了几行代码测试锁的问题,结果发现了一个调用Thread.sleep()的问题: ```public class Main { public static int value = 0; public static int value2 = 0; public static AtomicInteger aValue = new AtomicInteger(0); public static synchronized void increment2(){ value2++; } public static void main(String[] args) throws InterruptedException { for(int i=0;i<1000;i++){ new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } value++; Main.increment2(); Main.aValue.getAndIncrement(); } }).start(); } Thread.sleep(100); //问题在这一行!!!!!**** System.out.println(Main.aValue); } } 问题是: 理论上,我创造1000个线程分别对变量加一,执行完循环后,如果不加Thread.sleep(),打印出的三个value全是0,但是只有加上sleep,才能打印出理想结果,我想不明白这是什么原理。

下面的代码为什么输出不是1000?

public class ThreadTest { public static void main(String[] args) { final AtomicInteger atomicInteger = new AtomicInteger(0); for (int i = 0; i < 1000; i++) { new Thread(new Runnable() { @Override public void run() { atomicInteger.getAndIncrement(); } }).start(); } System.out.println(atomicInteger.toString()); } }

加不加Volatile看不出有什么效果啊

[code="java"]import java.util.concurrent.atomic.AtomicInteger; public class VolatilePattern1 extends Thread{ volatile boolean shutdownRequested; private AtomicInteger count = new AtomicInteger(); public void shutdown() { shutdownRequested = true; } public void run() { System.out.println("Thread:" + Thread.currentThread().getName()+" started."); while (!shutdownRequested) { System.out.println("working ..."+count); count.getAndIncrement(); try { Thread.sleep(50); } catch(InterruptedException ie) { ie.printStackTrace(); } } } public static void main(String[] args) { System.out.println("Thread:" + Thread.currentThread().getName()+" started."); VolatilePattern1 vp = new VolatilePattern1(); vp.start(); try { Thread.sleep(2000); } catch(InterruptedException ie) { ie.printStackTrace(); } finally { vp.shutdown(); } } }[/code]

WEB应用中业务Id锁有什么好的实现方案吗?

就是不需要某个方法锁住所有进来的线程,而是根据相同id来锁。除了String的intern()、或者concurrentMap这样的。 ``` public class ResourceLock { private static final Log log = LogFactory.get(ResourceLock.class); // 初始化ConcurrentHashMap锁载体 private static final ConcurrentHashMap<String, AtomicInteger> lockMap = new ConcurrentHashMap<String, AtomicInteger>(); public static AtomicInteger getAtomicInteger(String key) { if (lockMap.get(key) == null) {// 当实体ID锁资源为空,初始化锁 lockMap.putIfAbsent(key, new AtomicInteger(0));// 初始化一个竞争数为0的原子资源 } int count = lockMap.get(key).incrementAndGet();// 线程得到该资源,原子性+1 log.debug("资源ID为:" + key + ",争抢线程数:".ne + count); return lockMap.get(key);// 返回该ID资源锁 } public static void giveUpAtomicInteger(String key) { if (lockMap.get(key) != null) {// 当实体ID资源不为空,才可以操作锁,防止抛出空指针异常 int source = lockMap.get(key).decrementAndGet();// 线程释放该资源,原子性-1 if (source <= 0) {// 当资源没有线程竞争的时候,就删除掉该锁,防止内存溢出 lockMap.remove(key); log.debug("资源ID为:" + key + "移除成功"); } log.debug("资源ID为:" + key + ",争抢线程数:" + source); } } } ```

谁能提供一个能用的JAVA的Websocket聊天室

在下载频道下载了N个都不能用,项目能跑起来却提示连接不上,在此求各位dalao给一个能用的JAVA的Websocket聊天室,或者指导下这个项目为啥能跑起来却连接不上http://download.csdn.net/download/wendysunday123/9788097 在线等,挺急的,今天解答的后面追加悬赏50

两个问题,1、是线程一直没有结束,2、System.out.println("--------------dataNum = " + dataNum);这句输出的值也不争确,请指教.

public class T05_ThreadPool { public static void main(String[] args) throws InterruptedException { ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue<>(); for (int i = 0; i < 10000; i++) { queue.offer(i); } AtomicInteger dataNum = new AtomicInteger(0); ExecutorService service = Executors.newFixedThreadPool(8); //execute submit int queueSize = queue.size(); for (int i = 0; i < queueSize; i++) { service.execute(new Runnable(){ @Verride public void run(){ try{ if(!queue.isEmpty()){ System.out.println("-------" + queue.poll() + "-------"); TimeUnit.MILLISECONDS.sleep(500); dataNum.addAndGet(1); }else{ service.shutdown(); System.out.println("--------------dataNum = " + dataNum); } }catch(Exception e){ e.printStackTrace(); service.shutdown(); } } }); } System.out.println(service); } }

condition.await()并发问题

public class BlockArrayList<E> extends ArrayList<E> { /** * long serialVersionUID:TODO(用一句话描述这个变量表示什么) * * @since 1.0.0 */ private static final long serialVersionUID = 1L; private ReentrantLock lock = new ReentrantLock(); private Condition notEmpty = lock.newCondition(); public int i = 0; public Exception ee; public E take() throws InterruptedException { try { lock.lock(); E e = null; int size = this.size(); if(size == 0) { notEmpty.await(); } i++; System.out.println(i); try { e = this.remove(0); } catch(Exception e1) { ee = e1; } return e; } finally { lock.unlock(); } } public boolean offer(E e) { try { lock.lock(); this.add(e); notEmpty.signal(); return true; } finally { lock.unlock(); } } public void op() { E s = null; try { s = this.take(); } catch (InterruptedException e) { System.out.println(Thread.currentThread().getName() +" 被动结束"); e.printStackTrace(); } } public class MyThreadFactory implements ThreadFactory { private AtomicInteger NUMBER = new AtomicInteger(0); @Override public Thread newThread(Runnable r) { Thread t = new Thread(r); t.setName("shaoweiThread-"+NUMBER.decrementAndGet()); return t; } } public static void main(String[] args) { final BlockArrayList<String> list = new BlockArrayList<String>(); ThreadFactory threadThread = list.new MyThreadFactory(); Thread t = threadThread.newThread(new Runnable() { @Override public void run() { int i = 0; while(i <410000) { list.op(); } } }); t.start(); threadThread.newThread(new Runnable() { @Override public void run() { int i = 0; while(i <410000) { list.op(); } } }).start(); threadThread.newThread(new Runnable() { @Override public void run() { for(int i=0;i<400000;i++) { boolean flag = list.offer("item" + i); if(!flag) { System.out.println("添加元素失败"); } } System.out.println(list.ee); } }).start(); System.out.println("主线程结束"); } } 多个线程去取阻塞队列为啥会有并发问题呢?i正常应该为400000的,谁能给解释下

关于++操作线程安全问题的疑惑

[code="java"] public class TestSynchronizedThread implements Runnable{ private static Integer si = 0; private static AtomicInteger flag = new AtomicInteger(); @Override public void run() { for(int k=0;k<200000;k++){ synchronized(si){ si++; } } } public static void main(String[] args) throws InterruptedException{ TestMultiThread t1 = new TestMultiThread(); TestMultiThread t2 = new TestMultiThread(); ExecutorService exec1 = Executors.newCachedThreadPool(); ExecutorService exec2 = Executors.newCachedThreadPool(); exec1.execute(t1); exec2.execute(t2); while(true){ if(flag.intValue()==2){ System.out.println("si>>>>>"+si); break; } Thread.sleep(50); } } }[/code] 这段代码最后结果si打印出来小于400000,为什么加了synchronized后++操作还会产生中间状态,而我在JVM字节码中并未找到相应的证据佐证。 下面是主要JVM字节码: [code="java"] 0: iconst_0 1: istore_1 2: iload_1 3: ldc #2; //int 200000 5: if_icmpge 55 8: getstatic #3; //Field si:Ljava/lang/Integer; 11: dup 12: astore_2 13: monitorenter 14: getstatic #3; //Field si:Ljava/lang/Integer; 17: astore_3 18: getstatic #3; //Field si:Ljava/lang/Integer; 21: invokevirtual #4; //Method java/lang/Integer.intValue:()I 24: iconst_1 25: iadd 26: invokestatic #5; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 29: dup 30: putstatic #3; //Field si:Ljava/lang/Integer; 33: astore 4 35: aload_3 36: pop 37: aload_2 38: monitorexit 39: goto 49 42: astore 5 44: aload_2 45: monitorexit 46: aload 5 48: athrow 49: iinc 1, 1 52: goto 2 55: return [/code] 希望各位大侠能帮小弟指点一下迷津。

贴一段代码,一个id的生成器,求解

[code="java"] /* * This file is part of aion-unique <aion-unique.org>. * * aion-unique is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * aion-unique is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with aion-unique. If not, see <http://www.gnu.org/licenses/>. */ package com.aionemu.chatserver.utils; import java.util.BitSet; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.ReentrantLock; /** * Simplified version of idfactory * * @author ATracer */ public class IdFactory { private final BitSet idList = new BitSet(); private final ReentrantLock lock = new ReentrantLock(); private AtomicInteger nextMinId = new AtomicInteger(1); protected static IdFactory instance = new IdFactory(); public int nextId() { try { lock.lock(); int id = idList.nextClearBit(nextMinId.intValue()); idList.set(id); nextMinId.incrementAndGet(); return id; } finally { lock.unlock(); } } public static IdFactory getInstance() { return instance; } public static void main(String[] xiaoe) { BitSet idList = new BitSet(); for (int i = 0; i < 100; i++) System.out.println(idList.nextClearBit(i)); } } [/code] 我觉得有两个问题: 1. 这里既然已经用锁同步了,就可以不用atomic类 2. BitSet有点画蛇添足的味道 不知道作者为何要这么设计,求解。谁能指点下这么写的好处。

java.util.Stack是线程安全的么?

最近在学习java的并发包编程,写了一段代码,模仿原来测试ArrayList非安全代码来测试java.util.Stack是否是线程安全的。代码如下: [code="java"] package concurrent.lock.alg; import java.util.ArrayList; import java.util.List; import java.util.Stack; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; public class StackTest { private static final int ELEMENT_NUM = 51180; public static void main(String[] ben){ ExecutorService exec = Executors.newCachedThreadPool(); final Stack<String> stackStr = new Stack<String>(); for(int i=0;i<ELEMENT_NUM;++i){ exec.submit(new StackInsTask(stackStr)); } exec.shutdown(); try{ exec.awaitTermination(500, TimeUnit.SECONDS); }catch(InterruptedException e){ e.printStackTrace(); } List<String> testList = new ArrayList<String>(); while(!stackStr.empty()){ String dd = String.valueOf(stackStr.pop()); //System.out.println(dd); testList.add(String.valueOf(dd)); } //System.out.println(testList.size()); for(int i=1;i<=ELEMENT_NUM;++i){ if(!testList.contains(String.valueOf(i))){ System.out.println("didn't find"+i); } } } } class StackInsTask implements Runnable { public static AtomicInteger count = new AtomicInteger(); Stack stack; public StackInsTask(Stack s) { stack = s; } public void run() { stack.push(count.incrementAndGet()); } } [/code] 51180个线程同时启动,如果stack非安全,那么stack.push(count.incrementAndGet())插入的可能是同一个值。那么在: [code="java"] for(int i=1;i<=ELEMENT_NUM;++i){ if(!testList.contains(String.valueOf(i))){ System.out.println("didn't find"+i); } } [/code] [b]就会输出找不到的值,可是测试了几把发现好像是安全的,由于jdk也没说明stack是否是线程安全的,暂时没看源码,所以好奇来问下。顺便问下,eclipse看jdk源码需要下载些什么,这里偷个懒嘿嘿~[/b] ---------------------------------分割线,以下代码是证明ArrayList非安全的代码-------------------------------------- [code="java"] package com.concurrent.Amino.List; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; public class CommonListTest { private static final int ELEMENT_NUM = 28000; public static void main(String[] argvs) { ExecutorService exec = Executors.newCachedThreadPool(); // final List<String> listStr = new LockFreeList<String>(); final List<String> listStr = new ArrayList<String>(); for (int i = 0; i < ELEMENT_NUM; ++i) { exec.submit(new ListInsTask(listStr)); } exec.shutdown(); try { exec.awaitTermination(500, TimeUnit.SECONDS); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Size of list is" + listStr.size()); for (int i = 1; i <= ELEMENT_NUM; ++i) { if (!listStr.contains(i)) { System.out.println("didn't find " + i); } } System.out.println(ListInsTask.count.longValue()); } } class ListInsTask implements Runnable { public static AtomicInteger count = new AtomicInteger(); List list; public ListInsTask(List l) { list = l; } public void run() { if (list.add(count.incrementAndGet())) { //System.out.println("List Size = " + list.size()); } else { System.out.println("did not insert" + count.get()); } } } [/code]

在中国程序员是青春饭吗?

今年,我也32了 ,为了不给大家误导,咨询了猎头、圈内好友,以及年过35岁的几位老程序员……舍了老脸去揭人家伤疤……希望能给大家以帮助,记得帮我点赞哦。 目录: 你以为的人生 一次又一次的伤害 猎头界的真相 如何应对互联网行业的「中年危机」 一、你以为的人生 刚入行时,拿着傲人的工资,想着好好干,以为我们的人生是这样的: 等真到了那一天,你会发现,你的人生很可能是这样的: ...

程序员请照顾好自己,周末病魔差点一套带走我。

程序员在一个周末的时间,得了重病,差点当场去世,还好及时挽救回来了。

Java基础知识面试题(2020最新版)

文章目录Java概述何为编程什么是Javajdk1.5之后的三大版本JVM、JRE和JDK的关系什么是跨平台性?原理是什么Java语言有哪些特点什么是字节码?采用字节码的最大好处是什么什么是Java程序的主类?应用程序和小程序的主类有何不同?Java应用程序与小程序之间有那些差别?Java和C++的区别Oracle JDK 和 OpenJDK 的对比基础语法数据类型Java有哪些数据类型switc...

技术大佬:我去,你写的 switch 语句也太老土了吧

昨天早上通过远程的方式 review 了两名新来同事的代码,大部分代码都写得很漂亮,严谨的同时注释也很到位,这令我非常满意。但当我看到他们当中有一个人写的 switch 语句时,还是忍不住破口大骂:“我擦,小王,你丫写的 switch 语句也太老土了吧!” 来看看小王写的代码吧,看完不要骂我装逼啊。 private static String createPlayer(PlayerTypes p...

和黑客斗争的 6 天!

互联网公司工作,很难避免不和黑客们打交道,我呆过的两家互联网公司,几乎每月每天每分钟都有黑客在公司网站上扫描。有的是寻找 Sql 注入的缺口,有的是寻找线上服务器可能存在的漏洞,大部分都...

Intellij IDEA 实用插件安利

1. 前言从2020 年 JVM 生态报告解读 可以看出Intellij IDEA 目前已经稳坐 Java IDE 头把交椅。而且统计得出付费用户已经超过了八成(国外统计)。IDEA 的...

女程序员,为什么比男程序员少???

昨天看到一档综艺节目,讨论了两个话题:(1)中国学生的数学成绩,平均下来看,会比国外好?为什么?(2)男生的数学成绩,平均下来看,会比女生好?为什么?同时,我又联想到了一个技术圈经常讨...

总结了 150 余个神奇网站,你不来瞅瞅吗?

原博客再更新,可能就没了,之后将持续更新本篇博客。

副业收入是我做程序媛的3倍,工作外的B面人生是怎样的?

提到“程序员”,多数人脑海里首先想到的大约是:为人木讷、薪水超高、工作枯燥…… 然而,当离开工作岗位,撕去层层标签,脱下“程序员”这身外套,有的人生动又有趣,马上展现出了完全不同的A/B面人生! 不论是简单的爱好,还是正经的副业,他们都干得同样出色。偶尔,还能和程序员的特质结合,产生奇妙的“化学反应”。 @Charlotte:平日素颜示人,周末美妆博主 大家都以为程序媛也个个不修边幅,但我们也许...

MySQL数据库面试题(2020最新版)

文章目录数据库基础知识为什么要使用数据库什么是SQL?什么是MySQL?数据库三大范式是什么mysql有关权限的表都有哪几个MySQL的binlog有有几种录入格式?分别有什么区别?数据类型mysql有哪些数据类型引擎MySQL存储引擎MyISAM与InnoDB区别MyISAM索引与InnoDB索引的区别?InnoDB引擎的4大特性存储引擎选择索引什么是索引?索引有哪些优缺点?索引使用场景(重点)...

如果你是老板,你会不会踢了这样的员工?

有个好朋友ZS,是技术总监,昨天问我:“有一个老下属,跟了我很多年,做事勤勤恳恳,主动性也很好。但随着公司的发展,他的进步速度,跟不上团队的步伐了,有点...

我入职阿里后,才知道原来简历这么写

私下里,有不少读者问我:“二哥,如何才能写出一份专业的技术简历呢?我总感觉自己写的简历太烂了,所以投了无数份,都石沉大海了。”说实话,我自己好多年没有写过简历了,但我认识的一个同行,他在阿里,给我说了一些他当年写简历的方法论,我感觉太牛逼了,实在是忍不住,就分享了出来,希望能够帮助到你。 01、简历的本质 作为简历的撰写者,你必须要搞清楚一点,简历的本质是什么,它就是为了来销售你的价值主张的。往深...

魂迁光刻,梦绕芯片,中芯国际终获ASML大型光刻机

据羊城晚报报道,近日中芯国际从荷兰进口的一台大型光刻机,顺利通过深圳出口加工区场站两道闸口进入厂区,中芯国际发表公告称该光刻机并非此前盛传的EUV光刻机,主要用于企业复工复产后的生产线扩容。 我们知道EUV主要用于7nm及以下制程的芯片制造,光刻机作为集成电路制造中最关键的设备,对芯片制作工艺有着决定性的影响,被誉为“超精密制造技术皇冠上的明珠”,根据之前中芯国际的公报,目...

优雅的替换if-else语句

场景 日常开发,if-else语句写的不少吧??当逻辑分支非常多的时候,if-else套了一层又一层,虽然业务功能倒是实现了,但是看起来是真的很不优雅,尤其是对于我这种有强迫症的程序"猿",看到这么多if-else,脑袋瓜子就嗡嗡的,总想着解锁新姿势:干掉过多的if-else!!!本文将介绍三板斧手段: 优先判断条件,条件不满足的,逻辑及时中断返回; 采用策略模式+工厂模式; 结合注解,锦...

离职半年了,老东家又发 offer,回不回?

有小伙伴问松哥这个问题,他在上海某公司,在离职了几个月后,前公司的领导联系到他,希望他能够返聘回去,他很纠结要不要回去? 俗话说好马不吃回头草,但是这个小伙伴既然感到纠结了,我觉得至少说明了两个问题:1.曾经的公司还不错;2.现在的日子也不是很如意。否则应该就不会纠结了。 老实说,松哥之前也有过类似的经历,今天就来和小伙伴们聊聊回头草到底吃不吃。 首先一个基本观点,就是离职了也没必要和老东家弄的苦...

2020阿里全球数学大赛:3万名高手、4道题、2天2夜未交卷

阿里巴巴全球数学竞赛( Alibaba Global Mathematics Competition)由马云发起,由中国科学技术协会、阿里巴巴基金会、阿里巴巴达摩院共同举办。大赛不设报名门槛,全世界爱好数学的人都可参与,不论是否出身数学专业、是否投身数学研究。 2020年阿里巴巴达摩院邀请北京大学、剑桥大学、浙江大学等高校的顶尖数学教师组建了出题组。中科院院士、美国艺术与科学院院士、北京国际数学...

为什么你不想学习?只想玩?人是如何一步一步废掉的

不知道是不是只有我这样子,还是你们也有过类似的经历。 上学的时候总有很多光辉历史,学年名列前茅,或者单科目大佬,但是虽然慢慢地长大了,你开始懈怠了,开始废掉了。。。 什么?你说不知道具体的情况是怎么样的? 我来告诉你: 你常常潜意识里或者心理觉得,自己真正的生活或者奋斗还没有开始。总是幻想着自己还拥有大把时间,还有无限的可能,自己还能逆风翻盘,只不是自己还没开始罢了,自己以后肯定会变得特别厉害...

男生更看重女生的身材脸蛋,还是思想?

往往,我们看不进去大段大段的逻辑。深刻的哲理,往往短而精悍,一阵见血。问:产品经理挺漂亮的,有点心动,但不知道合不合得来。男生更看重女生的身材脸蛋,还是...

为什么程序员做外包会被瞧不起?

二哥,有个事想询问下您的意见,您觉得应届生值得去外包吗?公司虽然挺大的,中xx,但待遇感觉挺低,马上要报到,挺纠结的。

当HR压你价,说你只值7K,你该怎么回答?

当HR压你价,说你只值7K时,你可以流畅地回答,记住,是流畅,不能犹豫。 礼貌地说:“7K是吗?了解了。嗯~其实我对贵司的面试官印象很好。只不过,现在我的手头上已经有一份11K的offer。来面试,主要也是自己对贵司挺有兴趣的,所以过来看看……”(未完) 这段话主要是陪HR互诈的同时,从公司兴趣,公司职员印象上,都给予对方正面的肯定,既能提升HR的好感度,又能让谈判气氛融洽,为后面的发挥留足空间。...

面试:第十六章:Java中级开发

HashMap底层实现原理,红黑树,B+树,B树的结构原理 Spring的AOP和IOC是什么?它们常见的使用场景有哪些?Spring事务,事务的属性,传播行为,数据库隔离级别 Spring和SpringMVC,MyBatis以及SpringBoot的注解分别有哪些?SpringMVC的工作原理,SpringBoot框架的优点,MyBatis框架的优点 SpringCould组件有哪些,他们...

面试阿里p7,被按在地上摩擦,鬼知道我经历了什么?

面试阿里p7被问到的问题(当时我只知道第一个):@Conditional是做什么的?@Conditional多个条件是什么逻辑关系?条件判断在什么时候执...

Python爬虫,高清美图我全都要(彼岸桌面壁纸)

爬取彼岸桌面网站较为简单,用到了requests、lxml、Beautiful Soup4

差点跪了...

最近微信又搞出了一个大利器,甚至都上了热搜,当然消息最敏捷的自媒体人,纷纷都开通了自己的视频号。01 视频号是什么呢?视频号是微信体系内的短视频,它不同...

面试了一个 31 岁程序员,让我有所触动,30岁以上的程序员该何去何从?

最近面试了一个31岁8年经验的程序猿,让我有点感慨,大龄程序猿该何去何从。

Vue回炉重造之router路由(更新中)

你好,我是Vam的金豆之路,可以叫我豆哥。2019年年度博客之星、技术领域博客专家。主要领域:前端开发。我的微信是 maomin9761,有什么疑问可以加我哦,自己创建了一个微信技术交流群,可以加我邀请你一起交流学习。最后自己也创建了一个微信公众号,里面的文章是我自己精挑细选的文章,主要介绍各种IT新技术。欢迎关注哦,微信搜索:臻美IT,等你来。 欢迎阅读本博文,本博文主要讲述【】,文字通...

大三实习生,字节跳动面经分享,已拿Offer

说实话,自己的算法,我一个不会,太难了吧

程序员垃圾简历长什么样?

已经连续五年参加大厂校招、社招的技术面试工作,简历看的不下于万份 这篇文章会用实例告诉你,什么是差的程序员简历! 疫情快要结束了,各个公司也都开始春招了,作为即将红遍大江南北的新晋UP主,那当然要为小伙伴们做点事(手动狗头)。 就在公众号里公开征简历,义务帮大家看,并一一点评。《启舰:春招在即,义务帮大家看看简历吧》 一石激起千层浪,三天收到两百多封简历。 花光了两个星期的所有空闲时...

Java岗开发3年,公司临时抽查算法,离职后这几题我记一辈子

前几天我们公司做了一件蠢事,非常非常愚蠢的事情。我原以为从学校出来之后,除了找工作有测试外,不会有任何与考试有关的事儿。 但是,天有不测风云,公司技术总监、人事总监两位大佬突然降临到我们事业线,叫上我老大,给我们组织了一场别开生面的“考试”。 那是一个风和日丽的下午,我翘着二郎腿,左手端着一杯卡布奇诺,右手抓着我的罗技鼠标,滚动着轮轴,穿梭在头条热点之间。 “淡黄的长裙~蓬松的头发...

大胆预测下未来5年的Web开发

在2019年的ReactiveConf 上,《Elm in Action》的作者Richard Feldman对未来5年Web开发的发展做了预测,很有意思,分享给大家。如果你有机会从头...

立即提问
相关内容推荐