十四、同步器
倒计时门栓
倒计时门栓 设置倒计时数,倒计时减到 0 时,await的线程才能通过
适用于线程运行需要其他线程将数据准备好
// 倒计时门栓 设置倒计时数,倒计时减到 0 时,await的线程才能通过
// 适用于线程运行需要其他线程将数据准备好
CountDownLatch countDownLatch = new CountDownLatch(1);
int[] nums={0,0,0};
new Thread(()->{
try {
// 等待数据准备
countDownLatch.await();
// 可以设置等待时间,超过时间直接不等了,继续往下执行
//countDownLatch.await(10, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
nums[0]++;
System.out.println("执行");
}).start();
Thread.sleep(1000);
// 数据准备好了
nums[0]=1;
System.out.println("cutDown");
// 计数器-1 ,计数到 0 ,线程能继续运行了
countDownLatch.countDown();
障栅
障栅 ,适用于 当需要都所有线程都运行到一个位置,才能继续运行下去的时候
// 障栅 ,适用于 当需要都所有线程都运行到一个位置,才能继续运行下去的时候
// 参数:线程数
// CyclicBarrier 是可以复用的,当所有线程有到达障栅之后,便可以进行下次复用
CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
// 可以传入一个 Runnable 当所有线程都到达障栅的时候执行(执行一次,而不是每个线程都执行一次)
// CyclicBarrier cyclicBarrier =new CyclicBarrier(3,()-> System.out.println("所有线程都到达障栅"));
new Thread(()->{
try {
System.out.println("1 需要等待");
cyclicBarrier.await();
System.out.println("1 继续");
} catch (Exception e){
e.printStackTrace();
}
}).start();
new Thread(()->{
try {
System.out.println("2 需要等待");
cyclicBarrier.await();
// 如果设置了等待时间,则超时后或者await方法被中断,所有线程的await方法都会抛出 BrokenBarrier 异常
//cyclicBarrier.await(1, TimeUnit.NANOSECONDS);
System.out.println("2 继续");
} catch (Exception e){
e.printStackTrace();
}
}).start();
new Thread(()->{
try {
Thread.sleep(2000);
System.out.println("3 需要等待");
cyclicBarrier.await();
System.out.println("3 继续");
} catch (Exception e){
e.printStackTrace();
}
}).start();
交换器
可以让两个线程交换数据 ,可以用于如:两块数据区 分别用于生产者和消费者,生产者生产满了,消费者消费完了,二者交换数据区
// 可以让两个线程交换数据 ,可以用于如:两块数据区 分别用于生产者和消费者,生产者生产满了,消费者消费完了,二者交换数据区
Exchanger<Integer> exchanger = new Exchanger();
new Thread(()->{
Integer num= 1;
try {
// 等待交换数据,返回值为另一个线程提供的数据
num=exchanger.exchange(num);
System.out.println("线程1:"+num);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(()->{
Integer num= 2;
try {
num=exchanger.exchange(num);
System.out.println("线程2:"+num);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
// 线程2 :1
// 线程1 :2
同步队列
一个线程将数据传递给另一个线程
// 一个线程调用 put 方法时,会阻塞至另一线程调用 take方法 为止
// 因为实现了 BlockingQueue 接口,所以调用take 方法时,如果还没有 put 也会阻塞
SynchronousQueue synchronousQueue = new SynchronousQueue();
new Thread(()->{
try {
synchronousQueue.put(1);
System.out.println("put");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(()->{
try {
Thread.sleep(1000);
System.out.println("take");
synchronousQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
// take
// put
网友评论