"Java Programación Concurrente reales", señala el estudio (3)

Capítulo Cinco: Bloques de construcción

biblioteca plataforma contiene un rico conjunto de bloques de construcción concurrentes, tales como recipiente thread-safe y una variedad de herramienta de sincronización ( Synchronizer).

SynchronizerPara regular el flujo de control entre las roscas cooperantes.

contenedor síncrono

contenedores de sincronización se compone de dos partes, una Vectory HashTableson parte de la JDK temprana; el otro es su contenedor homólogos solamente se añadió en JDK 1.2 paquete de sincronización ( wrapper) clase.

Estas clases son un Collections.synchronizedXxxmétodo de fábrica crea.

El estado de estas clases por encapsulación de su estado, y sincronizar todos los métodos públicos para lograr el hilo de seguridad, por lo que sólo un hilo puede acceder al contenedor.

cuestiones síncronos contenedores emergente

contenedor síncrono son seguros hilo. Pero para operaciones complejas, a veces puede que tenga que utilizar el bloqueo de cliente adicional de protección (bloqueo del lado del cliente).

recipiente compuesto comprende generalmente: un proceso iterativo (elementos adquiridos repetidamente hasta que el último elemento en el recipiente), navegación (para encontrar el siguiente elemento de acuerdo con un cierto orden) y las condiciones de operación, tales como la "falta añadido es decir," (put-si- ausente), comprobar si hay Map clave K, y si no, la adición de mapeo (K, V).

En un contenedor síncrono, estas operaciones complejas, incluso si el cliente no se bloquea la protección, técnicamente apta para subprocesos, pero cuando los otros hilos a la modificación simultánea del contenedor, no podría funcionar como se espera.

/**
 * 操作Vector的复合操作可能导致混乱的结果
 */
public static Object getLast(Vector list) {
  int lastIndex = list.size() - 1;
  return list.get(lastIndex);
}
public static void deleteLast(Vector list) {
  int lastIndex = list.size() - 1;
  list.remove(lastIndex);
}

Aquí Insertar imagen Descripción

/**
 * 使用客户端加锁,对Vector进行复合操作
 */
public static Object getLast(Vector list) {
  synchronized (list) {
    int lastIndex = list.size() - 1;
    return list.get(lastIndex) ;
  }
}
public static void deleteLast(Vector list) {
  synchronized (list) {
    int lastIndex = list.size() - 1;
    list.remove(lastIndex);
  }
}

contenedores concurrentes

recipiente Java5.0 a través del contenedor para mejorar la clase de sincronización proporciona varias concurrente. recipiente de múltiples roscado concurrente está diseñado para acceso simultáneo.

  • Java 5.0 añade ConcurrentHashMappara reemplazar la correlación hash para lograr la sincronización
  • Cuando la operación de la mayoría es una operación de lectura, CopyOnWriteArrayListen lugar de la lista de ejecución sincrónica correspondientes

La nueva ConcurrentMapinterfaz se ha añadido soporte para operaciones complejas comunes, tales como "Falta que se añade a (poner ausente -si-)" , reemplazar y condiciones de borrado.

Alternativamente contenedores concurrentes contenedores síncrono, hay poco riesgo de este enfoque trae significativo aumento escalabilidad.

Java 5.0 también se añade dos nuevos tipos de contenedores: Queuey BlockingQueue.

  • QueueSe utiliza para retener temporalmente una serie de elementos están en espera de su procesamiento posterior. Sobre la base de Queueuna serie de implementación concreta.
  • BlockingQueueSe expandió Queue, el aumento de la obstrucción puede ser insertado y operaciones de adquisición. El bloqueo de la cola es muy útil en el diseño de los productores y consumidores.

Justo ConcurrentHashMapcomo la sincronización de hash de concurrente Mapa alternativa, Java 6 añadido ConcurrentSkipListMapy ConcurrentSkipListsetutilizado como síncronos SortedMapy SortedSetalternativas concurrentes (como un synchronizedMappaquete TreeMapo TreeSet).

ConcurrentHashMap

ConcurrentHashMapY HashMapcomo una tabla hash, pero utiliza una estrategia de bloqueo completamente diferente, podemos proporcionar mejor concurrencia y escalabilidad.

ConcurrentHashMapUtilice un mecanismo de bloqueo más granular, llamado el bloqueo de separación. Este mecanismo permite un mayor nivel de acceso compartido. Cualquier número de hilos de lectura simultáneas puede acceder al mapa, los lectores y los escritores pueden también acceso concurrente mapa, y un número limitado de escritura hilos concurrentes también puede modificar mapa. Como resultado de ello, conducir a un mayor rendimiento para el acceso simultáneo, mientras que casi sin pérdida de rendimiento de un solo acceso hilo.

El bloqueo de cola y productor - consumidor modelo

El bloqueo de cola ( BlockingQueue) proporciona un bloqueo puty takemétodos, y que puede ser temporizada offery pollson equivalentes.

El bloqueo de cola de apoyo productor - consumidor patrón de diseño. Un productor - consumidor diseño aislado "reconocimiento de que hay que hacer" y "aplicación". Este modo no pudo encontrar empleo será procesada inmediatamente, sino para trabajar en una tarea ( "hacer") lista, para preparar el procesamiento posterior.

Los productores y consumidores para producir diferentes velocidades o cambiar los datos y el consumidor, productor - modelo de consumo se desacoplar estas actividades, simplificando así la carga de trabajo de gestión.

Deque el trabajo y el robo

El mismo Java 6 dos tipos nuevo contenedor, Deque(cubierta pronunciada) y BlockingDequeque se amplían respectivamente Queuey BlockingQueue.

DequeEs un deque , permite la inserción y extracción de la cabeza y la cola, respectivamente eficiente. Se dan cuenta de que ArrayDequey LinkedBlockingDeque.

Como el bloqueo de cola correspondiente al productor - modelo de consumo, como la cola de doble extremo a sí mismos y se llama trabajo de robar (trabajo robar) los patrones asociados.

Un consumidor productor de diseño, todos los consumidores comparten solamente una cola de trabajo; robar el trabajo de diseño, cada cliente tiene su propia cola de doble extremo. Si un consumidor para completar todo el trabajo él mismo cola de doble composición, puede robar otros consumidores al final de la cola de tareas de doble extremo.

Debido a que el subproceso de trabajo y no compiten con una cola de tareas compartida, a fin de tratar de robar que el modo de funcionamiento tradicional del productor - consumidor diseño de una mejor escalabilidad, la mayoría de las veces acceder a su cola de doble extremo, reduciendo la competencia.

Cuando un trabajador tiene que tener acceso a otra cola, será tomado de la cola, en lugar de la cabeza, lo que reduce aún más la competencia por deque.

Sincronizador

SynchronizerEs un objeto que controla el regulador de flujo según el estado de la rosca en sí.

El bloqueo de cola pueden desempeñar un Synchronizerpapel; otros tipos Synchronizer, incluyendo semáforo (semáforo), puntos (barrera) y de cierre (pestillo).

Existen bibliotecas de la plataforma en algunas Synchronizerclases, como si ellos no pueden satisfacer sus necesidades, también puede seguir como se describe en el capítulo 14, crear una propia Synchronizer.

Todos Synchronizertienen derecho a características estructurales similares: encapsulan estado y estos estados para determinar la ejecución del hilo en un punto determinado se pasa o obligados a esperar, sino que también proporcionan método de control de estado, y espera eficiente Synchronizermétodo en el estado deseado.

cierre patronal

Latch (pestillo) es una Synchronizer, se puede retrasar el progreso de la rosca hasta que el hilo alcanza el estado final (terminal).

Un bloqueo funciona como una puerta: Hasta el bloqueo de alcanzar el estado final, la puerta se ha cerrado, ningún hilo puede pasar, al final del estado viene, se abrió la puerta, permitiendo que pasen todas las discusiones.

Atresia se puede utilizar para asegurar que una actividad particular hasta después de la realización de otras actividades tienen lugar, como por ejemplo:

  • Para garantizar que el cálculo no se ejecuta hasta que los recursos que necesita para ser inicializadas. Enclavamiento un binario (dos estados) se puede utilizar para expresar "recurso se ha inicializado R", R y todas las actividades necesarias debe esperar en la primera atresia.
  • Para garantizar que un servicio no se inicia hasta otros servicios dependen de lo que ya ha comenzado. Cada servicio contendrá un pestillo binaria asociada; S abrirá primero el inicio del servicio que esperar a otros servicios en el bloqueo depende s, después de la salida, el bloqueo se libera S, S de manera que todos los servicios dependientes también pueden iniciar el proceso.
  • Espere hasta que todas las partes de las actividades están totalmente preparados para continuar el procesamiento, como todos los jugadores en los juegos multi-jugador si todo listo. un bloqueo de este tipo sea cuando todos los jugadores están listos, alcanzar el estado final.

CountDownlatchSe consigue un cierre flexible, para cada uno de estos casos; permite un hilo que esperar o más de un conjunto de eventos que ocurre.

estados de bloqueo incluyen un contador, inicializado a un número positivo, que se utiliza para mostrar la necesidad de esperar a que una serie de eventos.

método de cuenta atrás de la operación del contador disminuye para indicar ha ocurrido un evento, y espera método esperan para los alcances de contador a cero, punto en el cual todos los eventos han tenido lugar a esperar. Si el valor del contador no es cero entrada, método aguardan a bloquear hasta que el contador es cero, o de hilos de espera se interrumpe, y tiempo de espera.

FutureTask

FutureTaskTambién se puede utilizar como el bloqueo. ( FutureTaskAplicación del resumen describe un portátil calcular el resultado).

FutureTaskSe calcula mediante la Callableaplicación, lo que equivale a unos resultados portátiles Runnable, y hay tres estados: espera, y se completa la operación.

Completado incluyendo un fin a todos los cálculos de cualquier manera, incluyendo el final de lo normal, anormal y cancelado. Una vez FutureTaskque entra en el estado de finalización, nunca se detendrá en este estado.

Future.getEl comportamiento depende del estado de la tarea. Si se ha completado, getse puede obtener inmediatamente de nuevo los resultados, de lo contrario se bloqueará hasta que la tarea se transfiere al estado de finalización, a continuación, devuelve el resultado o lanzar una excepción.

FutureTaskEl resultado del cálculo se transfiere desde el hilo para ejecutar los resultados de los cálculos necesitan en este tema: FutureTaskel Estatuto para garantizar la seguridad liberar esta entrega construido sobre la base de los resultados de los anteriores.

/**
 * 使用FutureTask预载稍后需要的数据
 */
public class Preloader {
  
  private final FutureTask<ProductInfo> future = new FutureTask<ProductInfo>(new Callable<ProductInfo>() {
    public ProductInfo call() throws DataLoadException {
      return loadProductInfo();
    }
  });
  
  private final Thread thread = new Thread(future);

  public void start() {
    thread.start();
  }

  public ProductInfo get() throws DataLoadException, InterruptedException {
    try {
      return future.get();
    } catch (ExecutionException e) {
      Throwable cause = e.getCause();
      if (cause instanceof DataLoadException)
        throw (DataLoadException) cause;
      else
        throw launderThrowable(cause);
    }
  }
}

puntos

Nivel ( barrier) similar a la de bloqueo, que fueron capaces de bloquear un grupo de hilos, hasta que se producen ciertos eventos.

La diferencia clave es que los puntos de cierre, todas las discusiones deben llegar al mismo puesto de control, con el fin de continuar con el procesamiento.

Atresia está esperando un evento; punto de control está esperando otros hilos.

nivel de protocolo de lograr, ya que algunos miembros de la familia del lugar de recogida especificada en el centro comercial :. "Cada uno de nosotros en McDonald 6:00 Ver a un futuro no a la licencia, a continuación, vamos a decidir qué hacer a continuación."

CyclicBarrierPermitir a los miembros de un número dado de veces en un puesto de control, que es muy útil para el algoritmo iterativo paralelo, el algoritmo dividir un problema en una serie de sub-problemas independientes.

Cuando un hilo alcanza el await puesto de control, llamada, esperan será bloqueado hasta que todos los hilos han alcanzado el punto de control. Si todos los hilos han llegado al punto de control, puesto de control se rompe con éxito a través, de modo que todas las discusiones han sido puestos en libertad, el nivel se restablece para prepararse para el siguiente uso.

Si se llama a un tiempo de espera para esperar, o bloqueando el hilo se interrumpe, a continuación, los puntos serán considerados un fracaso, no todas las llamadas a través de finalización Await BrokenBarrierExceptionterminación.

Si pasa con éxito el nivel, awaitlas devoluciones para cada hilo alcanza un número de índice único, puede utilizarlo para "elección" para producir un líder, la siguiente iteración emprender algún trabajo especial.

/**
 * 在一个细胞的 自动系统中用CyclicBarrier协调计箅
 */
public class CellularAutomata {
  private final Board mainBoard;
  private final CyclicBarrier barrier;
  private final Worker[] workers;

  public CellularAutomata(Board board) {
    this.mainBoard = board;
    int count = Runtime.getRuntime().availableProcessors();
    this.barrier = new CyclicBarrier(count, () -> mainBoard.commitNewValues());
    this.workers = new Worker[count];
    
    for (int i = 0; i < count; i++) {
      workers[i] = new Worker(mainBoard.getSubBoard(count, i));
    }
  }

  private class Worker implements Runnable {
    private final Board board;

    public Worker(Board board) {
      this.board = board;
    }

    @Override
    public void run() {
      while (!board.hasConverged()) {
        for (int x = 0; x < board.getMaxX(); x++) {
          for (int y = 0; y < board.getMaxY(); y++) {
            board.setNewValue(x, y, computeValue(x, y));
          }
        }
        try {
          barrier.await();
        } catch (InterruptedException ex) {
          return;
        } catch (BrokenBarrierException ex) {
          return;
        }
      }
    }
    public void start() {
      for (int i = 0; i < workers.length; i++) {
        new Thread(workers[i]).start();
      }
      mainBoard.waitForConvergence();
    }
  }
}

Publicados 107 artículos originales · ganado elogios 88 · vistas 260 000 +

Supongo que te gusta

Origin blog.csdn.net/Code_shadow/article/details/104499407
Recomendado
Clasificación