Java ReentrantLock

来自WHY42

以前在做2D游戏的时候,对于游戏画面的刷新,实际上都是采用一个死循环去弄的,像这样:

while(true){
    //...
    update();
    sleep(10);
}

队列与锁

后来在做一个socket的后端时,也情不自禁的这样使用了。一直在考虑有没有更好的办法,无奈接触的少,可遇而不可求。最近又遇到了相同的问题:做一个短信发送的队列。先上代码:

ReentrantLock lock = new ReentrantLock();
Condition notEmpty = lock.newCondition();

final ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<String>();

void addTask(String t){
    lock.lock();
    try{
        System.out.println("+" + t);
        queue.add(t);
        notEmpty.signal();
    }
    finally{
        lock.unlock();
    }
}

void handle(){
    while(true){
        lock.lock();
        try{
            final String t = queue.poll();
            if(t == null){
                notEmpty.await();
            }
            else{
                new Thread(new Runnable(){

                    @Override
                    public void run() {
                        System.out.println("->" + t);
                        try {
                            Thread.sleep(new Random().nextInt(5000));
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        
                    }
                    
                }).start();
                
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        finally{
            lock.unlock();
        }
    }
}

主函数:

public static void main(String [] args){
    final QueueTest test = new QueueTest();
    Thread addThread = new Thread(new Runnable(){

        @Override
        public void run() {
            for(int i = 0; i < 100; i++){
                test.addTask(new Random().nextInt(10000) + "");
                try {
                    Thread.sleep(new Random().nextInt(100));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            
        }
        
    });
    addThread.start();
    test.handle();
}

这里使用了一个信号,当队列为空之后,线程就会等待,当调用了add方法添加之后,释放了信号,处理线程唤醒。不清楚是否有更好的做法。权且记录之。