到其他线程调用了unpark这个线程才会结束阻塞
// 一般像这种无限期等待的调了多少次park(false, 0)就要对于调同样次数的unpark才会完全解除阻塞
unsafe.park(false, 0);
}
输出:
2020-05-11 08:01:04 main is running...
2020-05-11 08:01:10 main continue...
2020-05-11 08:01:13 main continue...
再看一个案例:
public void test6() throws Exception {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(LocalDateTime.now().format(formatter) + " " + Thread.currentThread().getName()
+ " is running...");
// 这里让当前线程阻塞600s也就是10分钟,注意:如果park第一个参数是true的话,表示绝对时间,这个时间是毫秒级的,也就是系统时间,系统到这个绝对时间后才唤醒执行
unsafe.park(true, System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(600));
System.out.println(LocalDateTime.now().format(formatter) + " " + Thread.currentThread().getName()
+ " continue...");
} catch (Exception e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(LocalDateTime.now().format(formatter) + " " + Thread.currentThread().getName()
+ " is running...");
// 这里让当前线程阻塞600s也就是10分钟,注意:如果park第一个参数是true的话,表示绝对时间,这个时间是毫秒级的,也就是系统时间,系统到这个绝对时间后才唤醒执行
unsafe.park(true, System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(600));
// unsafe.park(true, System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(600));
System.out.println(LocalDateTime.now().format(formatter) + " " + Thread.currentThread().getName()
+ " continue...");
} catch (Exception e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
// 主线程休眠2秒
Thread.sleep(2000);
System.out
.println(LocalDateTime.now().format(formatter) + " " + Thread.currentThread().getName() + " is running...");
// 这里调了unpark方法,参数就是t1线程,unsafe.unpark唤醒了t1线程,使得t1线程不用等到10分钟立马就可以执行
unsafe.unpark(t1);
// 下面连续调用了两次unpark t2线程,但是结果只释放了一次令牌,如果把t2线程的unsafe.park注释去掉,那么t2线程会一直等到park的时间到后被唤醒执行,
unsafe.unpark(t2);
unsafe.unpark(t2);
System.out.println(LocalDateTime.now().format(formatter) + " " + Thread.currentThread().getName() + " over...");
}
输出如下:
2020-05-11 08:05:26 Thread-1 is running...
2020-05-11 08:05:26 Thread-0 is running...
2020-05-11 08:05:28 main is running...
2020-05-11 08:05:28 main over...
2020-05-11 08:05:28 Thread-1 continue...
2020-05-11 08:05:28 Thread-0 continue...
unsafe的park和unpark在JUC并发包下使用的特别多,后续再介绍吧
内存屏障
这个我没有深入的了解,网上找了些资料看了看,没有具体的实践过,大家可以了解下。
loadFence:保证在这个屏障之前的所有读操作都已经完成。
storeFence:保证在这个屏障之前的所有写操作都已经完成。
fullFence:保证在这个屏障之前的所有读写操作都已经完成。
其他
类加载,类实例化相关的一些方法,还有其他的方法,这里不再一一说明,虽然不常用,但是了解其运行原理,或者去研究一下jvm的源码对自己都是一种提升。
再见
好了,就胡扯到这里吧,文章里的都是个人理解和实践,难免会有理解错误和实践错误的,请各位看官多多指正。