在Java

时间:2015-10-07 09:21:18

标签: java multithreading caching concurrency

我要求在多线程环境中拥有一个消息队列缓存,每秒会有数千个请求到来。

如果队列不为空,则每个请求线程都应弹出队列中的消息(并且不应该传递重复消息)+减少db中的计数器。如果队列为空,则线程将获取固定数量的消息(例如100)来自DB并填充队列缓存(其他线程应该在队列填充时等待)然后弹出一条消息+递减db中的计数器并返回。

db中的弹出和递减计数器应该同步以避免任何不一致。

因此,从要求可以看出,缓存将具有更多的读取和删除(弹出)操作,但是更少的写入操作(仅当缓存为空时)。

现在我有一个同步方法getMessage,里面有一个ArrayList,我在这个方法中做了上面的操作(如果是空的,则弹出输出,然后弹出)但我显然面临很多争用问题。

如果在读取/删除时,并发线程获得不同的锁,并且在写入时,锁应该在整个缓存上,那么这将减少我的争用问题。

在这种情况下哪个java缓存最好?在负载中,由于这个原因我面临着低性能。请给我一些更好的主意。

1 个答案:

答案 0 :(得分:4)

而不是Synchronize,您可以查看ReentrantLocks。根据您的要求,Java中有一个ReentrantReadWriteLock类。您可以参考Java文档以获取详细信息。基本上,如果数据被更多的读取器线程访问而不是写入器线程,则建议使用ReentrantReadWriteLock

根据此实现,多个线程可以在不锁定的情况下读取相同的资源。但是对资源的单个写操作将锁定它,并且不允许同时进行其他读取或写入。

网上有很多样本示例,您可以参考实施ReentrantReadWriteLock

样品:

package concurrency.reentrantreadwrite;

import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReentrantReadWrite {
    public static ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
    public static StringBuffer message = new StringBuffer("a");

    public static void main(String[] args) throws InterruptedException{
    Thread t1 = new Thread(new Reader(lock, message));
    Thread t2 = new Thread(new WriterA(lock, message));
    Thread t3 = new Thread(new WriterB(lock, message));
    t1.start();
    t2.start();
    t3.start();
    t1.join();
    t2.join();
    t3.join();
    }
}


package concurrency.reentrantreadwrite;

import java.util.concurrent.locks.ReentrantReadWriteLock;

public class Reader implements Runnable 
{
    ReentrantReadWriteLock lock = null;
    StringBuffer message = null;

    public Reader(ReentrantReadWriteLock lock, StringBuffer message) {
    this.lock = lock;
    this.message = message;
    }

    public void run() 
    {
    for(int i = 0; i<= 10; i ++) 
    {
        if(lock.isWriteLocked()) {
        System.out.println("I'll take the lock from Write");
        }
        lock.readLock().lock();
        System.out.println("ReadThread " + Thread.currentThread().getId() + " ---> Message is " + message.toString() );
        lock.readLock().unlock();
    }
    }
}


package concurrency.reentrantreadwrite;

import java.util.concurrent.locks.ReentrantReadWriteLock;

public class WriterA implements Runnable 
{
    ReentrantReadWriteLock lock = null;
    StringBuffer message = null;

    public WriterA(ReentrantReadWriteLock lock, StringBuffer message) {
    this.lock = lock;
    this.message = message;
    }

    public void run() 
    {
    for(int i = 0; i<= 10; i ++) 
    {
        try {
        lock.writeLock().lock();
        message.append("a");
        }finally {
        lock.writeLock().unlock();
        }
    }
    }
}

package concurrency.reentrantreadwrite;

import java.util.concurrent.locks.ReentrantReadWriteLock;

public class WriterB implements Runnable 
{
    ReentrantReadWriteLock lock = null;
    StringBuffer message = null;

    public WriterB(ReentrantReadWriteLock lock, StringBuffer message) {
    this.lock = lock;
    this.message = message;
    }

    public void run() 
    {
    for(int i = 0; i<= 10; i ++) 
    {
        try {
        lock.writeLock().lock();
        message.append("b");
        }finally {
        lock.writeLock().unlock();
        }
    }
    }
}