线程间通信:Condition
信号量:Semaphore
信号量这个名字乍一看来和线程同步控制没有任何关系,但是信号量的功能比ReentrantLock还要强大。当我们new ReentrantLock()的时候,此时我们就有了一把锁,而信号量则是可以自己定义这个锁的个数。
Semaphore类提供了一下两个构造方法:
对于线程间通信,大家最熟悉的莫过于Object.wait()、Object.notify()了。Condition的使用与前面的方法类似。
void await() throws InterruptedException;
void awaitUninterruptibly();
long awaitNanos(long nanosTimeout) throws InterruptedException;
boolean await(long time, TimeUnit unit) throws InterruptedException;
boolean awaitUntil(Date deadline) throws InterruptedException;
void signal();
void signalAll();
- await():当前线程调用后,释放锁资源,进入等待状态;当其他线程调用signal()或者signalAll()时,线程会重新获得锁并继续执行。
- awaitUninterruptibly():与await()方法的唯一区别就是,不响应中断信号。(await是响应中断的)
- signal():唤醒一个等待中的线程,类似于Object.notify(),signalAll()则是唤醒所有等待中的线程,然后让其竞争执行。
public class ReenterLockCondition implements Runnable {
public static ReentrantLock lock = new ReentrantLock();
public static Condition condition = lock.newCondition();
@Override
public void run() {
try {
lock.lock();
System.out.println("Thread is await");
condition.await();
System.out.println("Thread is going on");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
ReenterLockCondition r1 = new ReenterLockCondition();
Thread t1 = new Thread(r1);
t1.start();
Thread.sleep(2000);
// 通知线程t1继续执行
lock.lock();
condition.signal();
lock.unlock();
}
}
上述示例代码可以看出,在t1执行的过程中,调用了await(),然后主线程中调用了signal(),让其继续执行。
信号量:Semaphore
信号量这个名字乍一看来和线程同步控制没有任何关系,但是信号量的功能比ReentrantLock还要强大。当我们new ReentrantLock()的时候,此时我们就有了一把锁,而信号量则是可以自己定义这个锁的个数。
Semaphore类提供了一下两个构造方法:
public Semaphore(int permits);
public Semaphore(int permits, boolean fair);
从构造方法可以看出,创建有容量的锁对象,同时还可以让其公平。其常用方法如下:
// 获取一个锁(响应中断)
public void acquire() throws InterruptedException;
// 获取一个锁(不响应中断)
public void acquireUninterruptibly();
// 尝试获得一个锁,若获取不到则立即返回false
public boolean tryAcquire();
// 尝试获得一个锁,并设置了最大等待时间
public boolean tryAcquire(long timeout, TimeUnit unit);
// 释放一个锁
public void release();
// 获得n个锁(响应中断)
public void acquire(int permits) throws InterruptedException;
// 获得n个锁(不响应中断)
public void acquireUninterruptibly(int permits);
// 获得n个锁,若获取不到则立即返回false
public boolean tryAcquire(int permits);
// 获得n个锁,并设置了最大等待时间
public boolean tryAcquire(int permits, long timeout, TimeUnit unit) throws InterruptedException;
// 释放n个锁
public void release(int permits);
下面展示一个简单的例子:
public class SemapDemo implements Runnable {
final Semaphore semp = new Semaphore(5);
@Override
public void run() {
try {
semp.acquire();
// 模拟耗时操作
Thread.sleep(2000);
System.out.println(Thread.currentThread().getId() + ": done!");
semp.release();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ExecutorService exec = Executors.newFixedThreadPool(20);
final SemapDemo demo = new SemapDemo();
for(int i = 0; i < 20; i++) {
exec.submit(demo);
}
}
}
上面代码创建了容量为5的锁,故每次打印的"done!"个数都是5。