摘要:大家好,今天我们来聊聊Java线程这个让人又爱又恨的话题。作为一个Java开发者,谁没在深夜里对着死锁日志抓狂过?谁没被ConcurrentModificationException折磨得怀疑人生?今天我们就用轻松的方式,聊聊线程那些事儿。
java线程杂谈:从入门到“放弃”?
大家好,今天我们来聊聊Java线程这个让人又爱又恨的话题。作为一个Java开发者,谁没在深夜里对着死锁日志抓狂过?谁没被ConcurrentModificationException折磨得怀疑人生?今天我们就用轻松的方式,聊聊线程那些事儿。
一、线程的诞生:是继承Thread还是实现Runnable?
新手必问:"创建线程到底用继承Thread还是实现Runnable?"
答案很简单:优先选Runnable!为什么?
但面试官总爱追问:"那Callable和Future呢?"
悄悄告诉你:当需要返回值或抛异常时,它们才是真香组合!
二、线程状态:比女朋友的心情还复杂
线程的6种状态(别数了,Java定义的就是6种):
NEW:刚new出来还没start的萌新RUNNABLE:在JVM眼里,就绪和运行都算runnableBlockED:拿着爱的号码牌等锁的苦主WAITING:望眼欲穿等唤醒的痴情种(wait/join)TIMED_WAITING:设了闹钟的等待(sleep(1000))TERMINATED:领盒饭退场经典面试题:"sleep和wait的区别?"
sleep是Thread的静态方法,不释放锁wait是Object的方法,释放锁还要被notify三、同步的艺术:synchronized的千层套路
java
// 对象锁的三种姿势
public synchronized void method {} // 等同于锁this
public void method { synchronized(this) {} }
public void method { synchronized(obj) {} }
// 类锁的正确打开方式
public static synchronized void staticMethod {} // 锁Class对象
但synchronized太重了怎么办?
试试ReentrantLock的三大绝招:
四、线程池:别重复造轮子!
为什么要用线程池?看看这血泪史:
频繁创建/销毁线程开销大不加管控的线程可能OOM缺乏统一管理(拒绝策略、监控等)Executor框架的四大天王:
java
复制
Executors.newCachedThreadPool; // 线程数弹性伸缩
Executors.newFixedThreadPool(8); // 固定大小
Executors.newSingleThreadExecutor; // 单线程串行执行
Executors.newScheduledThreadPool(3); // 定时任务专家
但阿里规约为什么不让直接用Executors?
因为默认队列无界可能OOM!推荐手动newThreadPoolExecutor,七参数配置更灵活。
五、并发工具包:JUC大法好
CountDownLatch:老板等所有员工下班锁门java
CountDownLatch latch = new CountDownLatch(3);
// 三个线程分别countDown
latch.await; // 阻塞直到计数器归零
CyclicBarrier:旅游团集合点等人齐发车java
CyclicBarrier barrier = new CyclicBarrier(5, ->System.out.println("发车!"));
semaphore:海底捞等位区的叫号机java
Semaphore semaphore = new Semaphore(5); // 5个许可
semaphore.acquire; // 获取许可
semaphore.release;
ConcurrentHashMap:线程安全的哈希表(比Hashtable高到不知哪里去了)六、那些年我们踩过的坑
死锁现场:Ø 必要条件:互斥、占有且等待、不可抢占、循环等待
Ø 破局方法:jstack查线程栈,VisualVM在线监控
内存可见性:Ø volatile解决可见性问题(但不保证原子性)
Ø 经典案例:while(!stopFlag)可能永远不停止
ThreadLocal的魔幻现实:Ø 每个线程独立副本
Ø 但用完要remove!否则线程池复用会导致数据错乱
七、新世界大门:Java 8+的并发黑科技
CompletableFuture:异步编程利器java
CompletableFuture.supplyAsync( -> "hello")
.thenApply(s -> s + " world")
.thenAccept(System.out::println);
并行流(Parallel Stream):一行代码实现并行处理java
IntStream.range(1,100).parallel.sum;
StampedLock:读写锁的升级版,乐观读锁提升性能结语:多线程修炼指南
精读《Java并发编程实战》(虽然可能看三遍才懂)多写demo,用jstack、VisualVM等工具分析参与开源项目,看别人怎么写并发代码牢记:没有银弹! 不同场景选择不同方案互动话题:你遇到过最诡异的并发bug是什么?欢迎在评论区分享你的血泪史!
来源:老客数据一点号