Não há muito a dizer, basta ir ao código: a
primeira classe de ferramenta CountDownLatch:
CountDownLatch: CountDownLatch tem principalmente dois métodos, quando um ou mais threads chamam o método await, o thread de escrita será bloqueado. Quando outras threads chamam o método CountDownLatch, o contador será decrementado em 1 (a thread que chama o método CountDownLatch não será bloqueada). Quando o valor do contador se tornar 0, a thread bloqueada pelo método await será ativada e continuará a execução.
Vejamos um exemplo para comparação: 10 pessoas todas saem pela porta e, em seguida, trancam a porta.
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "出来了");
}, String.valueOf(i)).start();
}
System.out.println("锁门");
}
// 0出来了
// 锁门
// 3出来了
// 2出来了
// 1出来了
// 5出来了
// 6出来了
// 4出来了
// 8出来了
// 7出来了
// 9出来了
Obviamente não podemos fazer isso. Como podemos ter certeza de que a porta está trancada quando todas as 10 pessoas saem?
Neste momento, podemos usar nosso
código CountDownLatch da classe de ferramenta da seguinte maneira:
CountDownLatch countDownLatch = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "出来了");
countDownLatch.countDown();
}, String.valueOf(i)).start();
}
countDownLatch.await(); //减到0才继续
System.out.println("锁门");
// 0出来了
// 3出来了
// 1出来了
// 2出来了
// 4出来了
// 5出来了
// 7出来了
// 6出来了
// 8出来了
// 9出来了
// 锁门
Se não for reduzido a 0, estará sempre bloqueado aqui!
A segunda classe de ferramenta CyclicBarrier:
CyclicBarrier é semelhante à primeira, podemos olhar para seu construtor:
CyclicBarrier(int parties, Runnable barrierAction)
创建一个新的 CyclicBarrier ,当给定数量的线程(线程)等待时,它将跳闸,当屏障跳闸时执行给定的屏障动作,由最后一个进入屏障的线程执行。
Avançar no código.
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(10, () -> {
System.out.println("锁门");
});
for (int i = 0; i < 10; i++) {
int finalI = i;
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "第" + finalI + "出门");
try {
cyclicBarrier.await();
System.out.println(finalI);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}, String.valueOf(i)).start();
}
}
O resultado é o seguinte:
Podemos descobrir que todos os encadeamentos estão bloqueados aqui pelo método await (). Quando um determinado número de encadeamentos (encadeamentos) estão esperando, ele desarmará. Quando a barreira for acionada, a ação de barreira fornecida será executada e a última entrará. Execução de rosca da barreira.
A terceira classe de ferramenta Semáforo:
Imagine uma cena de agarramento de vagas de estacionamento. Se houver 3 ou 6 vagas de estacionamento, o código é o seguinte:
public class SemaphoreDemo {
public static void main(String[] args) {
Semaphore semaphore= new Semaphore(3);//模拟资源类,有3个空车位 为1的时候相当于synchronized
for(int i=0;i<6;i++){
new Thread(()->{
try {
semaphore.acquire(); //占用
System.out.println(Thread.currentThread().getName()+"\t抢占到了车位");
Thread.sleep(3000);
System.out.println(Thread.currentThread().getName()+"\t离开了车位");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
semaphore.release();//交还车位
}
},String.valueOf(i)).start();
}
}
}
Os resultados da execução são os seguintes:
Definimos duas operações no semáforo:
- adquirir (aquisição) Quando um encadeamento chama a operação de aquisição, ele deve adquirir o semáforo (o semáforo menos 1) ou esperar até saber que um encadeamento
libera o semáforo ou acorda - Na verdade, a liberação adiciona 1 ao valor do semáforo e, em seguida, ativa o segmento de espera.
Os semáforos são usados principalmente para dois propósitos, um é adequado para uso mutuamente exclusivo de vários recursos compartilhados e o outro é adequado para controlar o número de threads simultâneos