最后
面试前一定少不了刷题,为了方便大家复习,我分享一波个人整理的面试大全宝典
- Java核心知识整理
Java核心知识
- Spring全家桶(实战系列)
- 其他电子书资料
Step3:刷题
既然是要面试,那么就少不了刷题,实际上春节回家后,哪儿也去不了,我自己是刷了不少面试题的,所以在面试过程中才能够做到心中有数,基本上会清楚面试过程中会问到哪些知识点,高频题又有哪些,所以刷题是面试前期准备过程中非常重要的一点。
以下是我私藏的面试题库:
通过volatile
这种实现比较简单,也很好理解,但是性能不咋地,会抢占很多cpu资源,如非必要,不要用
public class VolatileTest {
//定义一个共享变量用来线程间通信,注意用volatile修饰,保证它内存可见
static volatile boolean flag = false;
static double year;
public static void main(String[] args) {
//线程A,练习唱跳rap
Thread threadA = new Thread(() -> {
while (true) {
if (!flag) {
for (year = 0.5; year <= 5; year += 0.5) {
System.out.println("开始练习唱跳rap:已练习" + year + "年");
try {
Thread.sleep(288);
} catch (InterruptedException e) {
e.printStackTrace();
}
//众所周知,练习两年半即可出道
if (year == 2.5) {
System.out.println("===========================>练习时长两年半,出道!!!");
// 通知threadB你可以执行了
flag = true;
//同样留意这个break
break;
}
}
break;
}
}
});
//线程B,练习打篮球
Thread threadB = new Thread(() -> {
while (true) {
// 监听flag
if (flag) {
System.out.println("开始练习打篮球");
break;
}
}
});
threadA.start();
threadB.start();
}
}
结果与上面第一个一样,就不展示了
关于break,我这里先不说,你先猜猜结果,再复制demo去跑跑,一定要动手
synchronized、wait()、notify()三件套
wait() 和 notify()都是Object类的通讯方法,注意一点,wait和 notify需搭配synchronized使用,注意,notify不会释放锁,至于不会释放锁体现在哪儿,这个demo下面有说明
public class SynchronizedTest {
static double year;
public static void main(String[] args) {
SynchronizedTest sync= new SynchronizedTest();
sync.execute();
}
public void execute() {
//线程A,练习唱跳rap
Thread threadA = new Thread(() -> {
synchronized (this) {
for (year = 0.5; year <= 5; year += 0.5) {
try {
System.out.println("开始练习唱跳rap:已练习" + year + "年");
Thread.sleep(288);
if (year == 2.5) {
System.out.println("===========================>练习时长两年半,出道!!!");
//唤醒等待中的threadB,但threadB不会立马执行,而是等待threadA执行完,因为notify不会释放锁
notify();
break;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
//线程B,练习打篮球
Thread threadB = new Thread(() -> {
synchronized (this) {
try {
wait();
System.out.println("开始练习打篮球");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//注意,一定要先启动B,不然会导致B永远阻塞
threadB.start();
threadA.start();
}
}
这个threadA里面的break一定要多想想,跑一跑你就知道啥叫不会释放锁
如果没有break,threadA在唤醒threadB后,会继续执行自己的逻辑,等自己执行完了才会释放锁,这时候threadB才开始执行
基于ReentrantLock
ReentrantLock是juc包下的并发工具,也能实现,但相对复杂,需结合Condition的await和signal,底层原理有点像上面的wait和notify
这里留个课后作业:思考一下为什么unlock要放在finally里面?
public class ReentrantLockTest {
static double year;
public static void main(String[] args) {
//实例化一个锁和Condition
ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
//线程A,练习唱跳rap
Thread threadA = new Thread(() -> {
lock.lock();
try {
for (year = 0.5; year <= 5; year += 0.5) {
System.out.println("开始练习唱跳rap:已练习" + year + "年");
Thread.sleep(288);
//众所周知,练习两年半即可出道
if (year == 2.5) {
System.out.println("===========================>练习时长两年半,出道!!!");
//唤醒等待中的线程
condition.signal();
//这里的break也是个彩蛋,去掉它触发隐藏关卡
break;
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//解锁
lock.unlock();
}
});
//线程B,练习打篮球
Thread threadB = new Thread(() -> {
lock.lock();
try {
//让当前线程等待
condition.await();
System.out.println("开始练习打篮球");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
});
//必须保证B先拿到锁,不然会导致A永远阻塞
threadB.start();
threadA.start();
}
}
基于CountDownLatch
这也是juc包下的并发工具,主要有两个常用方法,countDown和await
简单说下原理:CountDownLatch底层维护了一个计数器count,在实例化的时候设置,当调用countDown方法时,count减一,如果count在减一前已经为0,那么什么都不会发生,如果减一后变成0,则唤醒所有等待的线程;await方法会使当前线程等待,直到count为0
public class CountDownLatchTest {
static double year;
public static void main(String[] args) {
//实例化一个CountDownLatch,count设置为1,也就是说,只要调用一次countDown方法就会唤醒线程
CountDownLatch latch = new CountDownLatch(1);
//线程A,练习唱跳rap
Thread threadA = new Thread(() -> {
for (year = 0.5; year <= 5; year += 0.5) {
System.out.println("开始练习唱跳rap:已练习" + year + "年");
try {
Thread.sleep(288);
} catch (InterruptedException e) {
e.printStackTrace();
}
//众所周知,练习两年半即可出道
if (year == 2.5) {
System.out.println("===========================>练习时长两年半,出道!!!");
//计数器减一
latch.countDown();
//老规矩,去掉break触发隐藏关卡
break;
}
}
});
//线程B,练习打篮球
Thread threadB = new Thread(() -> {
try {
//阻塞当前线程,计数器为0时被唤醒
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("开始练习打篮球");
});
threadA.start();
threadB.start();
}
}
打完收工
写在最后
还有一份JAVA核心知识点整理(PDF):JVM,JAVA集合,JAVA多线程并发,JAVA基础,Spring原理,微服务,Netty与RPC,网络,日志,Zookeeper,Kafka,RabbitMQ,Hbase,MongoDB,Cassandra,设计模式,负载均衡,数据库,一致性哈希,JAVA算法,数据结构,加密算法,分布式缓存,Hadoop,Spark,Storm,YARN,机器学习,云计算…
,YARN,机器学习,云计算…
[外链图片转存中…(img-CfaHoJWB-1715483537975)]