juc之基本概念详解分析

基本概念

中断

  1. boolean interrupted() 返回当前调用线程,不是调用该方法的实例对象是否中断,若是中断,清除中断标志位
  2. boolean isinterrupted() 返回调用线程是否中断**,若是中断,恢复中断标志位**
  3. void interupt() 将调用线程中断标志为true
public static boolean interrupted() {
        return currentThread().isInterrupted(true);
    }

可以看到interrupted返回的是当前调用线程的中断状态

public class Test {
    public static void main(String[] args) throws InterruptedException{
        Thread thread=new Thread(new Runnable() {
            @Override
            public void run() {
                for(;;){}
            }
        });
        thread.start();
        System.out.println(thread.isInterrupted());
        thread.interrupt();
        System.out.println(thread.isInterrupted());
        System.out.println(thread.interrupted());
        System.out.println(Thread.interrupted());
        System.out.println(thread.isInterrupted());
    }
}
false
true    // 还是中断状态
false   // 此处是主线程的中断状态
false   
true

wait/park/sleep/await/yield/join

  • wait/(notify | notify) wait或者notify的前提是获得共享变量的锁(监视器),wait了之后会放弃持有锁,同样得到锁才能notify进行唤醒,唤醒后也不是立刻就能执行,还需要重新获得锁。
public class Test {
    public static void main(String[] args) throws InterruptedException {
        Integer a = 3;    // 共享变量
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (a) {
                    try {
                        System.out.println("before wait   "+System.currentTimeMillis());
                        a.wait();      // 调用了wait(0)
                        System.out.println("wait is ending   "+System.currentTimeMillis());
                    } catch (Exception e) {

                    }
                }
            }
        });
        thread.start();
        Thread.sleep(2000);
        synchronized (a) {
            a.notify();
            Thread.sleep(4000);
        }
    }
}
before wait   1561814784666
wait is ending   1561814790685    // 隔了6000ms

可以看到,首先子线程需要获得共享变量的Monitor,才能进行wait。再接着主线程需要获得Monitor才能进行notify。同时,notify后子线程并不能立刻运行,还是需要等获得Monitor才能从wait方法返回

 public final native void wait(long timeout) throws InterruptedException;

wait源码如上图所示,timeout若是0,则只能等待notify唤醒。若不是0的正数时间,在时间范围内,若是没有notify,到时间就会不再等待,返回就绪状态等Monitor。

  • park/unpark LockSupport(挂起和唤醒线程的工具类)的一对。调用park方法的线程若是没有许可证,就被阻塞,直到有unpack唤醒它。或者先执行unpack给当前线程颁发许可证,之后再执行pack的话会立刻返回。
public class Test {
    public static void main(String[] args) throws InterruptedException {
       Thread thread=new Thread(new Runnable() {
           @Override
           public void run() {
               System.out.println("before park  "+System.currentTimeMillis());
               LockSupport.park();     // 没有许可证第一次park会被阻塞
               System.out.println("after park    "+System.currentTimeMillis());
           }
       });
       thread.start();
       Thread.sleep(2000);
       LockSupport.unpark(thread);
    }
}
before park  1561816399926
after park    1561816401934      // 第一次park被阻塞2秒

接着是先unpark发许可证,再接park,会立刻返回

public class Test {
    public static void main(String[] args) throws InterruptedException {
       Thread thread=new Thread(new Runnable() {
           @Override
           public void run() {
             //  LockSupport.unpark(thread);
               LockSupport.unpark(Thread.currentThread());   // 注意这里边应该是当前线程,运行时确定
               System.out.println("before park  "+System.currentTimeMillis());
               LockSupport.park();     // 没有许可证第一次park会被阻塞
               System.out.println("after park    "+System.currentTimeMillis());
           }
       });
       thread.start();
    }
}
before park  1561817436822
after park    1561817436822    // 立刻返回
  • sleep时候被中断会抛出InterruptedException,sleep不会放弃锁,处于阻塞状态,时间到了后处于就绪状态
  • await condition.await类似于wait,需要先获得条件变量的锁。signal则是类似于notify;
  • 线程调用yield,代表让出cpu的使用权,此时该线程处于就绪状态,cpu开始线程调度(可能还调用这个线程)。
  • 调用join后当前线程一直阻塞,等待目标线程执行完毕

CountDownLatch/CyclicBarrier

  • CountDownLatch
public class Test implements  Runnable{
    static  final CountDownLatch end=new CountDownLatch(10);
    static  final  Test TEST=new Test();

    @Override
    public void run() {
        try {
            System.out.println("test");
            end.countDown();        // 计数器减一
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ExecutorService exec= Executors.newFixedThreadPool(10);
        for(int i=0;i<10;i++){
            exec.submit(TEST);
        }
        end.await();                // 主线程等待所有线程执行完成
        System.out.println("okok");
        exec.shutdown();
    }
}
test
test
test
test
test
test
test
test
test
test
okok
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值