如何在Java中找到一个线程安全的集合,在插入时强制执行唯一性和大小限制?

问题描述 投票:0回答:1

我正在寻找 Java 中的线程安全集合:

  1. 强制元素的唯一性(如集合)。
  2. 限制集合的大小(一旦达到限制,拒绝进一步插入)。
  3. 默认情况下本机执行此操作(无需自定义逻辑或包装另一个集合)。

到目前为止,我考虑过:

  1. ConcurrentSkipListSet
    为了唯一性,但没有大小限制。
  2. BlockingQueue
    用于大小控制,但它不强制唯一性。
  3. 使用 ConcurrentHashMap.newKeySet() 实现唯一性并手动管理大小的自定义实现。

是否有一个标准的 Java 线程安全集合可以提供这两种功能(唯一性和大小限制)而无需自定义处理?还是我需要实施自己的解决方案?

java multithreading collections
1个回答
0
投票

或者我需要实施自己的解决方案吗?

是的,您确实需要自己的实现。

采纳 Markspace 的评论中的建议,我编写了这个类,通过重写 Java 23 中的三个 ConcurrentSkipListSet

 方法来扩展 
add…
 来限制其大小。

我不是这方面的专家,所以使用需要您自担风险。

package work.basil.example.collecting;

import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.Semaphore;

public class LimitedSizeConcurrentSkipListSet < E > extends ConcurrentSkipListSet < E >
{
    private final Semaphore addingSemaphore = new Semaphore( 1 );
    private final int sizeLimit = 2 ;

    @Override
    public boolean add ( E e )
    {
        try
        {
            this.addingSemaphore.acquire();
            if(this.size() > this.sizeLimit) throw new IllegalStateException("Size of set should never exceed its limit.");
            if(this.size()==this.sizeLimit) return false;
            return super.add( e );
        }
        catch ( InterruptedException ex )
        {
            throw new RuntimeException( ex );
        }
        finally
        {
            addingSemaphore.release( );
        }

    }

    @Override
    public void addFirst ( E e )
    {
        try
        {
            this.addingSemaphore.acquire();
            if(this.size() > this.sizeLimit) throw new IllegalStateException("Size of set should never exceed its limit.");
            if(this.size()==this.sizeLimit) return ;
            super.addFirst( e );
        }
        catch ( InterruptedException ex )
        {
            throw new RuntimeException( ex );
        }
        finally
        {
            addingSemaphore.release( );
        }
    }

    @Override
    public void addLast ( E e )
    {
        try
        {
            this.addingSemaphore.acquire();
            if(this.size() > this.sizeLimit) throw new IllegalStateException("Size of set should never exceed its limit.");
            if(this.size()==this.sizeLimit) return ;
            super.addFirst( e );
        }
        catch ( InterruptedException ex )
        {
            throw new RuntimeException( ex );
        }
        finally
        {
            addingSemaphore.release( );
        }
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.