Visão geral da classe de contêiner simultâneo Java

0) Razão:

   Inicialmente, na era dos requisitos de baixo desempenho do programa, basicamente a programação de thread único, a CPU era basicamente de núcleo único. Com o desenvolvimento da tecnologia de hardware do computador, apareceram CPUs de múltiplos núcleos e a programação de núcleo único no passado não conseguiu usá-lo melhor. O número de núcleos de nossa CPU, juntamente com os crescentes requisitos de velocidade e desempenho do programa, emergiu da tecnologia de programação simultânea.O gargalo de desempenho dos programas de núcleo único é a alternância frequente de contexto, para que possamos melhorar o desempenho reduzindo a alternância de contexto. Deixe mais CPUs trabalharem juntas de forma assíncrona.

1) processo de desenvolvimento:

        Java é um kit de ferramentas de simultaneidade adicionado ao Java5. Este pacote contém uma série de classes que facilitam e facilitam a programação simultânea em Java. Antes disso, você precisa implementar manualmente a classe de ferramenta relevante.O caminho do pacote é fornecido no formato de uma classe de ferramenta como java.util.concurrent

        Classes fornecidas:

    • BlockingQueue
    • ArrayBlockingQueue
    • DelayQueue
    • LinkedBlockingQueue
    • PriorityBlockingQueue
    • Fila síncrona
    • Deque de bloqueio
    • Fila de extremidade dupla bloqueada em cadeia LinkedBlockingDeque
    • Mapa simultâneo ConcurrentMap
    • ConcurrentNavigableMap
    • Bloquear ConutDownLatch
    • CyclicBarrier
    • Permutador
    • Semáforo
    • ExecutorService
    • ThreadPoolExecutor
    • ExecutorService agendado
    • ForkJoinPool para garfo e mesclagem
    • Bloquear
    • ReadWriteLock
    • AtomicBoolean
    • AtomicInteger
    • AtomicLong
    • AtomicReference

      Escolhemos os mais usados ​​para uma visão geral.

2) Conhecimento teórico necessário

O bloqueio pessimista
sempre assume o pior caso. Toda vez que você obtém os dados, pensa que outras pessoas o modificam; assim, toda vez que você obtém os dados, eles são bloqueados, para que outros bloqueiem até obter o bloqueio ( Os recursos compartilhados são usados ​​apenas por um thread por vez, outros threads são bloqueados e os recursos são transferidos para outros threads após serem usados). Muitos desses mecanismos de bloqueio são usados ​​em bancos de dados relacionais tradicionais, como bloqueios de linhas, bloqueios de tabelas, bloqueios de leitura, bloqueios de gravação etc., que são bloqueados antes de executar as operações. Bloqueios exclusivos, como o sincronizado e o ReentrantLock em Java, são a realização de idéias de bloqueio pessimistas.

O bloqueio otimista
sempre assume a melhor situação: toda vez que você obtém dados, pensa que outras pessoas não os modificam e, portanto, não serão bloqueados, mas, ao atualizar, julgará se outras pessoas atualizaram esses dados durante esse período. Use o mecanismo do número da versão e o algoritmo CAS para obter. Os bloqueios otimistas são adequados para tipos de aplicativos com várias leituras, o que pode melhorar a taxa de transferência.Como o mecanismo write_condition fornecido pelo banco de dados, eles são realmente bloqueios otimistas. Em Java, a classe de variável atômica no pacote java.util.concurrent.atomic usa o CAS, uma implementação de bloqueio otimista.

CAS é uma tecnologia de bloqueio otimista . Quando vários threads tentam atualizar a mesma variável ao mesmo tempo usando o CAS, apenas um deles pode atualizar o valor da variável, enquanto os outros threads falham. O thread com falha não é suspenso, mas é notificado Falha nesta competição e pode tentar novamente

3) Os últimos desenvolvimentos:

           A primeira classe de coleção associada que aparece na biblioteca de classes Java é Hashtableque faz parte do JDK 1.0. HashtableEle fornece uma função de mapa associada fácil de usar e segura de threads, o que é obviamente conveniente. No entanto, a segurança do encadeamento tem um preço - Hashtabletodos os métodos são sincronizados. No momento, a sincronização não competitiva causará um custo de desempenho considerável. HashtableSucessor HashMapcomo parte de um conjunto de quadros JDK1.2 ocorrendo, fornecendo uma classe base e um invólucro síncrona sincronização Collections.synchronizedMapresolver as questões de segurança de rosca.

          Mas: O resultado é que, embora na superfície desses programas funcionem corretamente quando a carga é leve, mas uma vez que a carga é pesada, eles vão começar a jogar NullPointerExceptionouConcurrentModificationException 异常

随后出现了 ConcurrentMap

ConcurrentMap 的实现

concurrent 包里面就一个类实现了 ConcurrentMap 接口

  • ConcurrentHashMap
ConcurrentHashMap

ConcurrentHashMap 和 HashTable 类很相似,但 ConcurrentHashMap 能提供比 HashTable 更好的并发性能。在你从中读取对象的时候,ConcurrentHashMap 并不会把整个 Map 锁住。此外,在你向其写入对象的时候,ConcurrentHashMap 也不会锁住整个 Map,它的内部只是把 Map 中正在被写入的部分锁定。
其实就是把 synchronized 同步整个方法改为了同步方法里面的部分代码。

另外一个不同点是,在被遍历的时候,即使是 ConcurrentHashMap 被改动,它也不会抛 ConcurrentModificationException。尽管 Iterator 的设计不是为多个线程同时使用。


使用例子:

public class ConcurrentHashMapExample {

    public static void main(String[] args) {
//        HashMap<String, String> map = new HashMap<>();
        ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();
        map.put("1", "a");
        map.put("2", "b");
        map.put("3", "c");
        map.put("4", "d");
        map.put("5", "e");
        map.put("6", "f");
        map.put("7", "g");
        map.put("8", "h");
        new Thread1(map).start();
        new Thread2(map).start();

    }

}

class Thread1 extends Thread {

    private final Map map;

    Thread1(Map map) {
        this.map = map;
    }

    @Override
    public void run() {
        super.run();
        try {
            Thread.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        map.remove("6");
    }
}

class Thread2 extends Thread {

    private final Map map;

    Thread2(Map map) {
        this.map = map;
    }

    @Override
    public void run() {
        super.run();
        Set set = map.keySet();
        for (Object next : set) {
            System.out.println(next + ":" + map.get(next));
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}复制代码

CopyOnWriteArrayList

在那些遍历操作大大地多于插入或移除操作的并发应用程序中,一般用 CopyOnWriteArrayList 类替代 ArrayList 。如果是用于存放一个侦听器(listener)列表,例如在AWT或Swing应用程序中,或者在常见的JavaBean中,那么这种情况很常见(相关的 CopyOnWriteArraySet 使用一个 CopyOnWriteArrayList 来实现 Set 接口) 。

原理实现:

如果您正在使用一个普通的 ArrayList 来存放一个侦听器列表,那么只要该列表是可变的,而且可能要被多个线程访问,您 就必须要么在对其进行迭代操作期间,要么在迭代前进行的克隆操作期间,锁定整个列表,这两种做法的开销都很大。当对列表执行会引起列表发生变化的操作时, CopyOnWriteArrayList 并不是为列表创建一个全新的副本,它的迭代器肯定能够返回在迭代器被创建时列表的状态,而不会抛出 ConcurrentModificationException 。在对列表进行迭代之前不必克隆列表或者在迭代期间锁 定列表,因为迭代器所看到的列表的副本是不变的。换句话说, CopyOnWriteArrayList 含有对一个不可变数组的一个可变的引用,因此,只要保留好那个引用,您就可以获得不可变的线程安全性的好处,而且不用锁 定列表。


4)目前最新应用情况:

Tome ConcurrentHashMap como um exemplo:

versão jdk7

ConcurrentHashMap e HashMap têm idéias de design semelhantes, mas para oferecer suporte a operações simultâneas, algumas melhorias foram feitas.O ConcurrentHashMap introduz o conceito de Segmento, o objetivo é dividir o mapa em vários Segmentos (padrão 16). A operação ConcurrentHashMap é refinada para operar em um determinado segmento. Em um ambiente multithread, threads diferentes operam segmentos diferentes, eles não se afetam, o que pode alcançar operações simultâneas

A implementação mais recente do JDk8:

Comparado com a versão jdk7, o ConcurrentHashMap da versão jdk8 enviou muitas alterações: o jdk8 abandonou diretamente o design do segmento e adotou um design mais leve de Node + CAS + Synchronized para garantir a segurança do encadeamento.

807144-6264960638978dff.webp

Diagrama da estrutura ConcurrentHashMap

Observe a estrutura geral do ConcurrentHashMap acima, uma matriz de nós, o padrão é 16, pode ser expandida automaticamente, a velocidade de expansão é 0,75

private static finalint DEFAULT_CONCURRENCY_LEVEL = 16;
private static final float LOAD_FACTOR = 0.75f;

Cada nó monta uma lista vinculada Quando os dados de montagem da lista vinculada são maiores que 8, a lista vinculada é automaticamente convertida em uma árvore vermelha e preta.

static final int TREEIFY_THRESHOLD = 8;

Parte do código:

public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
    implements ConcurrentMap<K,V>, Serializable {
    transient volatile Node<K,V>[] table;
}

static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        volatile V val;
        volatile Node<K,V> next;
}

static final class TreeNode<K,V> extends Node<K,V> {
        TreeNode<K,V> parent;  // red-black tree links
        TreeNode<K,V> left;
        TreeNode<K,V> right;
        TreeNode<K,V> prev;    // needed to unlink next upon deletion
        boolean red;
}

static final class TreeBin<K,V> extends Node<K,V> {
        TreeNode<K,V> root;
        volatile TreeNode<K,V> first;
        volatile Thread waiter;
        volatile int lockState;
 }

Acho que você gosta

Origin www.cnblogs.com/dgwblog/p/12744213.html
Recomendado
Clasificación