JDK并发包详细总结(2)

// await()方法会使当前线程等待,同时释放当前锁,当其他线程中使用signal()时或者signalAll()方法时,
    // 线程会重新获得锁并继续执行。或者当线程被中断时,也能跳出等待。这和Object.wait()方法很相似。
    void await() throws InterruptedException;
    // awaitUninterruptibly()方法与await()方法基本相同,但是它并不会再等待过程中响应中断。
    void awaitUninterruptibly();
    long awaitNanos(long nanosTimeout) throws InterruptedException;
    boolean await(long time, TimeUnit unit) throws InterruptedException;
    boolean awaitUntil(Date deadline) throws InterruptedException;
    // singal()方法用于唤醒一个在等待中的线程。相对的singalAll()方法会唤醒所有在等待中的线程。
    // 这和Obejct.notify()方法很类似。
    void signal();
    void 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();
            condition.await();
            System.out.println("Thread is going on");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // 注意放到finally中释放
            lock.unlock();
        }
    }

public static void main(String[] args) throws InterruptedException {
        ReenterLockCondition t1 = new ReenterLockCondition();
        Thread tt = new Thread(t1);
        tt.start();
        Thread.sleep(2000);
        System.out.println("after sleep, signal!");
        // 通知线程tt继续执行. 唤醒同样需要重新获得锁
        lock.lock();
        condition.signal();
        lock.unlock();
    }
}

Semaphore信号量

锁一般都是互斥排他的, 而信号量可以认为是一个共享锁,

允许N个线程同时进入临界区, 但是超出许可范围的只能等待.

如果N = 1, 则类似于lock.

具体API如下, 通过acquire获取信号量, 通过release释放

1    public void acquire()
2    public void acquireUninterruptibly()
3    public boolean tryAcquire()
4    public boolean tryAcquire(long timeout, TimeUnit unit)
5    public void release()

示例

模拟20个线程, 但是信号量只设置了5个许可.

因此线程是按序每2秒5个的打印job done.

public class SemapDemo implements Runnable{

// 设置5个许可
    final Semaphore semp = new Semaphore(5);

@Override
    public void run() {
        try {
            semp.acquire();
            // 模拟线程耗时操作
            Thread.sleep(2000L);
            System.out.println("Job done! " + Thread.currentThread().getId());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            semp.release();
        }
    }

public static void main(String[] args){
        ExecutorService service = Executors.newFixedThreadPool(20);
        final SemapDemo demo = new SemapDemo();
        for (int i = 0; i < 20; i++) {
            service.submit(demo);
        }
    }
}

ReadWriteLock

读写分离锁, 可以大幅提升系统并行度.

读-读不互斥:读读之间不阻塞。

读-写互斥:读阻塞写,写也会阻塞读。

写-写互斥:写写阻塞。

示例

使用方法与ReentrantLock类似, 只是读写锁分离.

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/8791015b7c833f8476df32253f13fed6.html