semaphore
semaphore信号量,是并发编程的一个重要概念,表示可用资源的数量。信号量涉及的核心操作:P操作:申请一个资源(可用资源-1),V操作:释放一个资源(可用资源+1)与此同时,可用资源变化的操作均属于原子操作。
semaphore持有acquire()方法和release()方法,分别对应P操作和V操作。当可用资源为0时执行acquire方法时线程就会进入阻塞状态,执行release方法时就会释放资源使可用资源+1,这时被阻塞的线程将会竞争这份资源,获取到之后就会继续执行。
写了个例子:
场景:若干个人接水,只有两台饮水机:
用户类:
package Thread.semaphore;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.Semaphore;
public class Customer implements Runnable{
private Semaphore semaphore;
private String name;
public Customer(Semaphore semaphore , String name){
this.semaphore = semaphore;
this.name = name;
}
@Override
public void run() {
try {
SimpleDateFormat sdf = new SimpleDateFormat("HH:MM:ss");
Random random = new Random();
semaphore.acquire();
System.out.println(sdf.format(new Date())+" " + name + "开始接水");
Thread.sleep((long) (random.nextDouble() * 5000) + 2000);
System.out.println(sdf.format(new Date())+" "+name+"接满水了");
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
测试类:
package Thread.semaphore;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Semaphore;
public class Service {
public static void main(String[] args) throws InterruptedException {
Semaphore semaphore = new Semaphore(2);
List<Thread> list = new ArrayList<>();
list.add(new Thread(new Customer(semaphore,"小a")));
list.add(new Thread(new Customer(semaphore,"小b")));
list.add(new Thread(new Customer(semaphore,"小c")));
list.add(new Thread(new Customer(semaphore,"小d")));
list.add(new Thread(new Customer(semaphore,"小e")));
for(Thread thread : list){
thread.start();
}
for(Thread thread : list){
thread.join();
}
}
}
结果:
CountDownLatch
类似于计数器的功能,他可以让一个或多个线程进入等待状态直至其他线程完成工作。比如说多线程下载一个文件,只有每个线程都下载完毕才能算文件下载完毕。常用于分布式系统。
CountDownLatch持有countdown方法和await方法,当线程调用countdown的时候计数器将会减一,当线程调用await方法的时候,如果计数器不为0,则该线程进入阻塞状态,直到计数器为0时就会直接退出。
写了个例子:
场景:运动场上长跑的5位选手,全部跑完之后才算比赛结束。
运动员类:
package Thread.CountDownLatch;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
public class sportsman implements Runnable{
private CountDownLatch countDownLatch ;
private String name;
public sportsman(CountDownLatch countDownLatch , String name){
this.countDownLatch = countDownLatch;
this.name = name;
}
@Override
public void run() {
try {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
Random random = new Random();
Thread.sleep((long)(random.nextDouble()*3000));
System.out.println(sdf.format(new Date())+" " + name + "到达终点");
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
测试类:
package Thread.CountDownLatch;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public class Service {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(5);
List<Thread> list = new ArrayList<>();
list.add(new Thread(new sportsman(countDownLatch,"小a")));
list.add(new Thread(new sportsman(countDownLatch,"小b")));
list.add(new Thread(new sportsman(countDownLatch,"小c")));
list.add(new Thread(new sportsman(countDownLatch,"小d")));
list.add(new Thread(new sportsman(countDownLatch,"小e")));
for(Thread thread:list){
thread.start();
}
System.out.println("比赛开始");
countDownLatch.await();
System.out.println("比赛结束");
for(Thread thread : list){
thread.join();
}
}
}
结果: