Java多线程总结
1、多线程的作用:发挥多核CPU的优势
2、创建线程的方式:继承Thread类、实现Runable接口(方式更灵活,也可以减少程序间的耦合度)。
3、start()方法和run()方法的区别:只有调用了start()方法才会表现出多线程的特性;不同线程的run()方法里面的代码时交替执行。
4、Runnable接口和Callable接口的区别:Runnable接口的run()方法返回值是void,Callable接口的call()方法有返回值。
5、volatile关键字作用:使用该关键字修饰的变量,保证了多线程之间的可见性,每次读到volatile变量,一定是最新数据;使用volatile会禁止JVM对底层指令的重排序,一定程度上降低了代码执行效率。
6、线程安全:代码在多线程下执行和在单线程下执行的结果都一样,说明是线程安全的。
线程非安全的类:ArrayList、LinkedList、HashMap。
线程安全的类:Vector、Stack、HashTable、StringBuffer。
7、线程dump(线程堆栈):解决死循环、死锁、阻塞、页面打开慢等问题。获取线程堆栈步骤:
获取线程的pid(jps或ps -ef | grep java);
打印线程堆栈(jstack pid、kill -3 pid)
8、线程运行出现异常:如果异常没有被捕获,线程就停止了。如果这个线程持有某个对象的监视器,那这个对象监视器会被立即释放。
9、如何在两个线程之间共享数据:通过线程之间共享对象实现,然后通过wait/notify/notifyAll、await/signal/signalAll进行唤起和等待。实现的数据结构:阻塞队列。
10、sleep方法和wait方法区别:两者都可以用来放弃CPU一定的时间。不同点为如果线程持有某个对象的监视器,sleep方法不会放弃这个对象的监视器,wait方法会放弃这对象的监视器。
11、生产者和消费者模型的作用:通过平衡生产者的生产能力和消费者的消费能力来提升整个系统的运行效率;解耦,可以独自发展而不需要收到相互的制约。
12、ThreadLocal作用:空间换时间的做法,在每个Thread里面维护了一个以开地址法实现的ThreadLocal.ThreadLocalMap,把数据进行隔离,数据不共享,就没有线程安全方面的问题。