Directorio de artículos
Prefacio
Y luego java.util.concurrent
el paquete, hay varias operaciones de herramientas auxiliares. Como CountDownLatch 减法计数器
, CyclicBarrier 加法计数器
y Semaphore 信号量
.
Me sorprendió escuchar acerca de estas categorías. Ahora hablemos sobre cómo usar estas tres categorías de herramientas.
CountDownLatch down counter
Dado el tamaño y la capacidad inicial, se llama cada vez que un subproceso realiza una operación, y la capacidad es -1. Cuando
no hay datos en él, continuará realizando otras operaciones.
Mira las siguientes castañas:
import java.util.concurrent.CountDownLatch;
/**
* 减法 计数器;用于 必须保证所有线程都执行完后继续其他操作。
*/
public class CountDownTest {
public static void main(String[] args) throws InterruptedException {
// 1、计数器对象的创建,并给定计数器初始大小数
CountDownLatch countDownLatch = new CountDownLatch(6);
// 开启多个线程执行操作
for (int i = 1; i <= 6; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+" get ticket");
// 2、每个线程执行某项操作时,将计数器-1
countDownLatch.countDown();
},String.valueOf(i)).start();
}
// 3、等待计数器中的数据门票消耗完
countDownLatch.await();
// 4、打印信息
System.out.println("ticket num 0");
}
}
El resultado de la ejecución es el siguiente:
[发现:]
Use
await()
, después de dejar que otros subprocesos terminen de ejecutarse, continuará esperando, un poco similarthread 中的 join()
, esperará a que todos los subprocesos terminen de ejecutarse antes de continuar con otras operaciones a continuación.
Consulte el manual de desarrollo de jdk 1.8, que explica el método de la siguiente manera:
Contador de adición de CyclicBarrier
Como se mencionó anteriormente 减法计数器
, debe haberlo 加法计数器
. Su funcionamiento se CyclicBarrier
basa en:.
Mira el siguiente ejemplo:
package demo5_1;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
* 加法计数器
*/
public class CyclicBarrierDemo {
public static void main(String[] args) {
// 创建 10个 大小的 计数器
//CyclicBarrier cyclicBarrier = new CyclicBarrier(10);
CyclicBarrier cyclicBarrier = new CyclicBarrier(10,()->{
System.out.println("票售完");
});
// 创建多线程
for (int i = 1; i <= 10 ; i++) {
new Thread(()->{
// 打印信息
System.out.println(Thread.currentThread().getName()+" get ticket");
// 计数器等待
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
},String.valueOf(i)).start();
}
}
}
La información de impresión del registro después de la ejecución es la siguiente:
[发现:]
1. Se define un contador de adiciones al principio y el método de construcción adoptado es el siguiente
public CyclicBarrier(int parties, Runnable barrierAction)
.
2. Después de que cada hilo ejecute algún negocio, llámelocyclicBarrier.await()
, lo que equivale a agregarlo a la lista de monitoreo.
3, cuando el volumen establecido esté completamente ocupado, activaráCyclicBarrier(int parties, Runnable barrierAction)
elRunnable
.
Ver await()
la lógica de ejecución del código fuente :
Semáforo
La clase de herramienta de semáforo se usa generalmente para clases de recursos limitados. Durante el
subproceso múltiple, si un número limitado de subprocesos están completamente ocupados, solo se permite que los subprocesos desocupados esperen;
cuando se libera el subproceso inicialmente ocupado, los subprocesos subsiguientes para ser utilizados.
Similar a la siguiente lógica:
Es
令牌桶
muy similar a la lógica de los algoritmos. tal como请求限流!
El proceso de visualización de la imagen sigue siendo muy abstracto, mire las siguientes castañas:
package demo5_1;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
/**
* 信号量:用于某资源占用,其他处理等待其他线程处理完后才能处理
*/
public class SemphoreDemo {
public static void main(String[] args) {
// 假设 座位只有3个
Semaphore semaphore = new Semaphore(3);
// 创建线程
for (int i = 1; i <= 12 ; i++) {
new Thread(()->{
try {
// 获取座位(此处会造成阻塞 必须等待有空位才会分配,即向下执行)
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+" 获取座位");
// 假设拿到座位后占用2秒
TimeUnit.SECONDS.sleep(2);
// 离开座位 原则上应该放在finally中执行 --- 释放资源操作
//semaphore.release();
//System.err.println(Thread.currentThread().getName()+" 离开座位");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
// 离开座位 原则上应该放在finally中执行--- 释放资源操作
semaphore.release();
// 用err只是颜色区分日志打印
System.err.println(Thread.currentThread().getName()+" 离开座位");
}
},String.valueOf(i)).start();
}
}
}
El registro de salida de la consola después de la ejecución es el siguiente: