1.semephore
semephore是什么?
semephore,它是一个信号量,可以当作一个计数器进行理解,它可以描述可用资源的个数。更加直观的理解就是它限制通过的线程量,比如它 只允许4个线程通过,可是有八个线程,那么他就会先获取四个线程,然后这四个线程运行完后,释放线程,然后再获取剩下的四个线程,运行后释放。这就跟锁差不多,锁只是只允许单线程通过,但是semephore是可以让用户自己设置的。如果设置为1,那么就称为二元信号量。这时候就基本跟锁的作用是一样的了。
semephore的用法?
semephore首先我们需要知道的就是semephore.acquire()是获取线程,它内部就会有一个计数器进行+1如果够了的话就会停止,semephore.release()是释放线程,释放一个计数器就会进行减一操作。实例化它的时候需要传一个限制线程的个数。
public static void main(String[] args) {
//一次只能用四个线程跑,当值为一时,就可以当作一个锁了
Semaphore semaphore=new Semaphore(4);
Runnable runnable=new Runnable() {
@Override
public void run() {
try {
//准备申请资源
System.out.println("准备申请资源");
semaphore.acquire();
//资源申请成功
System.out.println("资源申请成功");
Thread.sleep(1000);
//释放资源成功
System.out.println("释放资源完毕");
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
for (int i = 0; i < 20; i++) {
Thread thread=new Thread(runnable);
thread.start();
}
}
2.ReentrantLock
ReentrantLock是什么?
ReentrantLock是可重入互斥锁,他的使用可以类比synchronized。
ReentrantLock和synchronized的区别是什么?
synchronized已经很先进了,但是还有一些功能还是不太能满足需求。ReentrantLock就对synchronized进行了补充。
1.ReentrantLock可分为加锁和解锁两个方法,确实存在遗忘的风险,但是可提高代码的灵活性。比如把加锁和解锁操作分别放到两个方法中去。
2.ReentrantLock还提供了tryLock()方法,对于一般的Lock()方法,如果尝试加锁失败,就会阻塞等待。但是对于tryLock()方法,如果加锁失败就会直接返回出错,不会阻塞等待。
3.synchronized是一个非公平锁。但ReentrantLock它是可以设置是公平锁还是非公平锁
4.ReentrantLock提供了更加强大的唤醒机制,synchronized是搭配wait,notify进行使用的。而ReentrantLock是搭配了另一个Condition类来完成唤醒等待的,它能够指定唤醒那个等待的线程。
3.CountDownLatch
它可以自己指定维护几个线程,等这几个线程都进行完后才结束,不然就一直等待。比如就是一场长跑比赛,等最后一名线程跑完后才能算比赛结束,不然就一直等最后一名线程。
public static void main(String[] args) throws InterruptedException {
//限定需要完成线程的数量
CountDownLatch latch=new CountDownLatch(4);
Runnable runnable=new Runnable() {
@Override
public void run() {
System.out.println("准备");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("起跑");
try {
Thread.sleep((long) (Math.random()*10000));
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown();//给里面的计数器减一
System.out.println("到达终点");
}
};
for (int i = 0; i < 4; i++) {
Thread thread=new Thread(runnable);
thread.start();
}
//四个线程都走完,里面的计数器为0,结束
latch.await();
System.out.println("比赛结束");
}