问题集合
1、多线程常见问题之多线程安全问题
提到多线程,大家就会想到锁。
他们两个是两个概念。
用到多线程的场景多了去了,不是每个多线程都要加锁。
不操作共享变量就不会有线程安全问题。
共享数据有可能同时被两个线程操作,再加锁。
不能碰到多线程就想到线程安全,然后加锁。
锁的前提是你操作了共享变量,如果没有共享变量,是不存在数据安全问题的,并且不能盲目的追求速度快,忽视了数据的安全,本末倒置。
乱用锁的后果是性能降低或者死锁。
效率和数据安全是个跷跷板,A高了,B就低,合理的运用锁,才是正解。
另外ArrayList与HashMap本身亦是线程不安全的,他们本身没有针对线程级进行处理,所以在进行多线程操作时,就会出现线程安全问题。
2、多线程常见问题之多线程乱跑传参问题
多线程协同问题, 本身多线程是没有执行顺序的。
有的时候会遇到这样的场景,想提高效率,使用了多线程,但是方法与方法之间的传参乱套了。
这么多线程齐头乱跑,第二个线程要用到第一个线程的结果,怎么搞。
join()方法:当调用join()方法的线程结束之后,其他线程才可以跑。
将join()方法调用者的线程加入到当前线程,调用者这个线程执行完,在执行当前线程。
比如说将子线程.join();这行代码加入到主线程中,那么子线程先执行完,再走主线程后面的代码。
现在有两个线程A,线程B
不使用join()方法,两个线程争夺CPU执行权。
在线程B中使用线程A,结果就是一定先执行完线程A,才会执行线程B。
在线程A中使用线程B,结果就是一定先执行完线程B,才会执行线程A。
上图如下:
1、新建一个线程。
2、不加join()方法。
3、加入join()方法。
再举个例子:
总结:
如果你有两个线程A,线程B,线程B要使用线程A的结果,可以说是线程传参问题,怎么解决?
你可以使用join()方法,但你的执行速度肯定会变慢,那怎么办?
可以取巧一下,打个时间差,根据自己的业务来,不一定非要用户触发再跑多线程,提前跑了完事。
几十ms的时间,用户是感受不到的,但是如果就在这100ms内,多个线程一起跑,你还要利用其他线程的结果,肯定会有问题,计算机是能感受到多少多少ms的。
3、start()方法与run()方法区别
start()方法执行后,线程状态由新建状态进入运行状态。
run方法调用后,就是一个普通的方法,不涉及到线程层次。
4、wait()方法与sleep()方法区别
1、wait进入等待状态会释放锁,sleep不会释放锁。
2、wait是Object类的方法,sleep是Thread的方法。
3、wait必须在同步代码块使用,sleep任意。
4、wait可以指定时间进入计时等待也可以不指定进入无限等待,sleep必须指定时长。
5、继承Thread类与实现Runable接口有什么不同
1、适合多个相同的程序代码的线程共享同一个资源,比如声明成员变量。
2、面向接口编程,多实现,解决java中单继承的局限性问题。
3、增加程序的健壮性,实现解耦操作。
4、ThreadPoolExecutor线程池只能放入实现Runable或callable类线程,不能直接放入Thread类。
6、为什么wait/notify是Object类方法,而不是Thread
首先,java语言为什么叫java语言。
其次,wait方法为什么是Object类,你个杠精。
最后,等待唤醒方法是由锁来使用的,锁类型是任意类型,那么等待唤醒方法自然也就是Object类咯。
如果是Thread类,那么实现Runable接口的可不是线程类,难道多线程只能采用继承Thread类的方法吗。
7、Synchronized与ReentrantLock的区别
1、Synchronized由编译器保证锁的加锁和释放,而ReentrantLock需要手工声明来加锁和释放锁,容易忘记释放锁,造成死锁。
2、synchronized可以锁住方法和代码块,lock只可以锁住代码块。
3、API的区别,比如lock中有很多丰富功能的API。synchronized不可以中断,lock可以中断也可以不中断;synchronized只能是非公平锁,而reentrantLock可以指定是公平锁还是非公平锁。
4、Synchronized依赖于JVM实现,操作系统实现。ReentrantLock是jdk层次,一个接口,有源码可以阅读。
如果你需要使用很多API,比如判断某线程是否获取锁,判断等待队列中有哪些线程,那么这种情况下,lock锁是可以实现的,synchronized不可以。
8、volatile与synchronized的区别
1、volatile只能修饰实例变量和类变量,synchronized可以修饰方法,以及代码块。
2、volatile只能保证可见性和有序性,synchronized是一种排他互斥锁,可以保证三种特性。
3、两个都是关键字,lock是实实在在的jdk代码。
9、volatile与atomic的区别
1、volatile常用于修饰类似开关类型的变量,Boolean 类型的变量。
2、Atomic常用于计数器之类变量。