面试官问Java多线程?我差点直接笑出声

0 阅读3分钟

多线程啊,说出来你可能不信,它比我家猫抢沙发还难控制。面试的时候有人问我:“你对多线程熟吗?”我差点回答:“熟?我每天都在跟它打仗。”

好了,正经点,Java里搞线程就像开了一间厨房,厨师(线程)多了,锅(共享资源)有限。你得学会调度,否则乱套。

线程生成,别一言不发

Java里线程生成有两种方式,我记得面试官喜欢考这一点:

  1. 继承Thread:直接让厨师自告奋勇干活。
class EggCooker extends Thread {
    public void run() {
        System.out.println("煎蛋ing...");
    }
}
public class Demo {
    public static void main(String[] args) {
        Thread t = new EggCooker();
        t.start();
    }
}
  1. 实现Runnable接口:签合同,让人干活,但你可以随时换人。
class CoffeeMaker implements Runnable {
    public void run() {
        System.out.println("咖啡煮好了,闻到香味了吧!");
    }
}
public class Demo2 {
    public static void main(String[] args) {
        Thread t = new Thread(new CoffeeMaker());
        t.start();
    }
}

面试常问:“为什么不直接继承Thread?”答案就是——Java只支持单继承,你继承了Thread就不能继承别的类了,所以Runnable更灵活。记住这个回答,我当时一说,面试官点头了。

线程状态,别光背词儿

线程状态面试官问得多,不仅是NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED,还爱问“状态切换为什么会发生?”

我当时比喻:

  • NEW:刚入厨房,啥也没干
  • RUNNABLE:已经在厨房忙活了,随时准备炒菜
  • BLOCKED:锅被别人抢走,干瞪眼
  • WAITING/TIMED_WAITING:站一边等调料或者倒水
  • TERMINATED:活干完,回家睡觉

然后补一句:线程调度完全靠JVM和操作系统,你想让它顺序执行?呵呵,别做梦,除非你是面试官。

同步,锁,坑比比皆是

面试最爱问同步。为什么要同步?不用synchronized会怎样?我就说:“厨房锅没加锁,蛋和咖啡混一起,你吃了吗?”面试官笑,我也笑,但确实问题扎心。

示例:

class Counter {
    private int count = 0;

    public synchronized void inc() {
        count++;
        System.out.println(Thread.currentThread().getName() + " 计数:" + count);
    }
}

public class Demo3 {
    public static void main(String[] args) {
        Counter c = new Counter();
        for(int i=0; i<3; i++){
            new Thread(() -> c.inc(), "Thread-"+i).start();
        }
    }
}

面试常问:“synchronized的锁粒度怎么选?”
我当时心里想——粒度大了,效率低,粒度小了,死锁可能来袭,面试官就喜欢你思考这个。

线程池,不用它你就是傻

再说线程池,面试喜欢问FixedPool和CachedPool的区别。我说:

  • FixedPool:固定数量厨师,锅多了也等
  • CachedPool:厨师不够?临时雇,活完就解雇

代码随便写个示例:

import java.util.concurrent.*;

public class KitchenDemo {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(2);
        for(int i=0; i<5; i++){
            int finalI = i;
            pool.submit(() -> System.out.println("做菜-" + finalI + "完成"));
        }
        pool.shutdown();
    }
}

面试官问:“线程池的拒绝策略你知道吗?”我说:“知道,就是告诉我厨房爆满,别再叫我了。”

volatile、CAS、原子类,小心面试陷阱

volatile?面试喜欢问:“能保证原子性吗?”你心里默念三遍:不,不,不
CAS?乐观锁,面试官问你“ABA问题”,我当时想打个比方:有人换了锅,你没注意,又换回原来的锅,你还以为没动过——就ABA了。

面试真实感受

面试问线程的时候,别光背概念,要能说出感受。比如:“我做过一个日志处理系统,十几线程同时写,没加锁直接挂了,后来加了ReentrantLock,才稳得住。”
这类案例比任何官方词儿都能打动面试官。