JDK 并发包 - 同步控制

重入锁:ReentrantLock

相比synchronized, 重入锁有着显示的操作过程;

ReentrantLock lock = new ReentrantLock();

lock.lock();
lock.lock();

try{
    //do something
}finally{
    lock.unlock();
    lock.unlock();
}

一个线程可连续多次获得同一把锁,释放的时候需要释放相同的次数。如果过释放锁的次数过多,会得到异常 IllegalMonitorStateException 

中断响应

lock.lockInterruptibly();
  • 在等待锁的时候,可对中断响应,得到异常 InterruptedException

锁申请等待限时

boolean success = lock.tryLock(5,TimeUnit.SECONDES);
  • 第一个参数为等待时长,第二个参数计时单位
  • 成功获得锁返回true,等待时间内未获得锁返回false。
  • 也可以不带参数,如果锁未被其他线程占用,立即返回true,如果锁被其他线程占用,当前进程不会等待,立即放回false。

公平锁

ReentrantLock lock = new ReentrantLock(true);

公平锁需要一个有序队列,因此实现成本高,性能相对也非常低下。

 

 

条件:Condition

Condition和wait()、notify()方法的功能大致相同。但是 后者与 synchronized 关键字合作使用,而Conditon与重入锁相关联。

ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
//...
        @Override
        public void run(){
            try{
                lock.lock();
                condition.await();
            } catch( InterruptedException e){
                // 响应中断
            } finally{
                lock.unlock();
            }
        }
//...
    public static void main( String[] args)throws InterruptedException {
        lock.lock();
        condition.signal();
        lock.unlock();
    }

通过Lock 接口 可以生成一个与当前重入锁绑定的Condition实例。

await();
awaitUninterruptibly();
signal();
signalAll();

awaitUninterruptibly() 不会在等待中响应中断。

其他的与Object.wait()、Object.notify()、Object.notifyAll()类似。await()会释放占用的锁。

线程调用的时候,需要持有对应的重入锁。

 

 

信号量:Semaphore

public Semaphore( int permits);//指定permits 个数的线程,可同时访问。
public Semaphore( int permits, boolean fair);// 第二个参数指定是否公平

无论是内部锁synchronized 还是重入锁 ReentrantLock, 一次只允许一个线程访问一个资源。而信号量允许多个线程同时访问某个资源。

public void acquire();
public void  acquireUninterruptibly();
public boolean tryAcquire();
public boolean tryAcquire( long timeout; TimeUnit unit);
public void release();

实例:P84

 

 

读写锁:ReadWriteLock

ReadWriteLock 是JDK5中提供的读写分离锁。读写分离可有效地帮助减少锁竞争,以提升性能。

只有读-读之间不会阻塞,读-写、写-读、写-写 都会阻塞。

    ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    Lock readLock = readWriteLock.readLock();
    Lock wrieteLock = readWriteLock.writeLock();

    readlock.lock();
    readlock.unlock();

 

倒计时锁:CountDownLatch

调用countDownLatch.await()的线程等待,其他任务的完成(调用countDown())。

public class Test implements Runnable{
    static Test demo = new Test();
    static CountDownLatch count = new CountDownLatch(10);// 参数为计数个数

    @Override
    public void run() {
        try{
            Thread.sleep(1000);// 模拟任务
            count.countDown();// 通知CountDownLatch一个线程以及完成
        } catch (InterruptedException e) {
            // sleep 中断
        }
    }

    public static void main(String[] args){
        ExecutorService exec = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            exec.submit(demo);
        }
        try {
            count.await();// 等待所有N个线程调用了countDown()
        } catch (InterruptedException e) {
            // CountDownLatch.await() 中断
        }
    }
}

 

 

循环栅栏:CyclicBarrier

public class Test implements Runnable{

    static Test demo = new Test();
    static CyclicBarrier barrier = new CyclicBarrier(3, new Runnable() {
        @Override
        public void run() {
            System.out.println("本次循环完毕!");
        }
    });

    @Override
    public void run() {
        try {
            System.out.println("正在等待的线程数:" + barrier.getNumberWaiting());
            barrier.await();
            System.out.println("第一个循环完成!");
            barrier.await();
            System.out.println("第二个循环完成!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws BrokenBarrierException, InterruptedException {
        for (int i = 0; i < 3; i++) {
            new Thread(demo).start();
            Thread.sleep(1000);
        }
    }
}
  • 当调用N次 barrier.await()后,计数器完成一次计数,并执行第二参数Runnable(最后一个调用await()的线程会直接在本线程中调用run()方法,然后调用signalAll()唤醒前面等待的线程 )。
  • CyclicBarriar 可能抛出两个异常:InterruptedException 和 其特有的BrokenBarrierException,表示当前的CyclicBarrier已经损坏了,在执行就没有意义了。比如其中一个调用barrier.await()的线程被中断了,那么其他调用barrier.await()的线程再继续等待就徒劳无功了。

 

 

线程阻塞工具:LockSupport

让调用LockSupport.park() 的线程阻塞,线程状态为WAITING,它不需要先获得某个对象的锁,也不会抛出InterruptedException

unpark()唤醒线程,不会因unpark()在park() 之前调用而永久挂起。

park();
parkNanos();
parkUntil();
park(Object);
unpark();

unpark函数为线程提供“许可(permit)”,线程调用park函数则等待“许可”。这个有点像信号量,但是这个“许可”是不能叠加的,“许可”是一次性的

此处个人理解为:线程的许可初始是不可用的,当先调用park()时,当前线程等待许可可用,调用unpark()使许可可用后,等待的线程继续执行;当先调用unpark()时,将不可用的许可变为可用,后续调用park()时,检测到许可可用,则立即直接返回,继续执行。 

 

转载于:https://my.oschina.net/u/3171491/blog/1511314

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
jdk-11-windows是指Java开发工具包(Java Development Kit)的第11个版本,适用于Windows操作系统。JDK是使用Java语言进行开发的应用程序和软件的环境,它提供了许多工具和功能,可用于编写、编译和运行Java程序。 JDK-11包含了许多新的特性和改进,使得Java编程更加方便和高效。其中一项突出的特性是JVM(Java虚拟机)的性能改进,它可以提供更快速和更高效的执行速度。其他一些特性包括G1垃圾回收器的增强和适用于观察、诊断和监控Java程序的Java Flight Recorder和Java Mission Control工具等。 对于Windows用户来说,JDK-11提供了易于安装和使用的Windows平台上的开发环境。它包括了JRE(Java运行环境)和用于开发、调试和测试Java应用程序的工具集。通过JDK-11,开发人员可以利用Windows操作系统的优势和特性,进行快速、高效和可靠的Java开发。 此外,JDK-11还提供了许多与安全性和稳定性相关的改进。它包含了新的安全性特性,可以帮助开发人员保护他们的应用程序免受潜在的安全威胁。另外,JDK-11还包含了一些稳定性改进,可以提高应用程序的性能和可靠性。 总之,JDK-11-windows是适用于Windows操作系统的Java开发工具包的最新版本。它提供了许多新的特性和改进,使得Java开发更加方便、高效和安全。对于Windows用户来说,使用JDK-11可以提供更好的开发体验,使他们能够更轻松地创建出优秀的Java应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值