✨1、如何在Java中实现线程?
可以继承java.lang.Thread 类或者实现Runnable接口来重写run()方法实现线程。
🎑2、Thread 类中的start() 和 run() 方法有什么区别
start()方法来启动线程,真正实现了多线程运行。
run()方法当作普通方法的方式调用。程序还是要顺序执行。
🎨3、Java中的volatile 变量是什么?有什么作用?
可见性,是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的。也就是一个线程修改的结果。另一个线程马上就能看到。
比如:用volatile修饰的变量,就会具有可见性。volatile修饰的变量不允许线程内部缓存和重排序,即直接修改内存。所以对其他线程是可见的。
在访问volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞,volatile变量是一种比sychronized关键字更轻量级的同步机制。
但因为不会加锁,所以不能保证线程安全。
深入了解:Java内存模型
🎃4、什么是线程安全?Vector是一个线程安全类吗?
如果代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行某段代码。
如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
Vector与ArrayList的实现类似,但Vector使用同步保证线程安全。
🎭5、线程间如何通信,进程间如何通信?
1). 共享变量;
2).wait(), notify() 方法;
3).Lock/Condition机制;
4).管道机制
⛳6、Java中notify 和 notifyAll有什么共同点和区别?
notify()和notifyAll()的共同点:均能唤醒正在等待的线程,并且均是最后只有一个线程获取资源对象的锁。
不同点:notify() 只能唤醒一个线程,而notifyAll()能够唤醒所有的线程,
当线程被唤醒以后所有被唤醒的线程竞争获取资源对象的锁,其中只有一个能够得到对象锁,执行代码。
🧸7、什么是ThreadLocal变量(重点)
ThreadLocal一般称为线程本地变量,它是一种特殊的线程绑定机制,将变量与线程绑定在一起,为每一个线程维护一个独立的变量副本。
通过ThreadLocal可以将对象的可见范围限制在同一个线程内。
🥓8、什么是线程池? 为什么要使用它?
从JDK1.5开始,Java API提供了Executor框架让你可以创建不同的线程池。
比如单线程池,每次处理一个任务;数目固定的线程池或者是缓存线程池(一个适合很多生存期短的任务的程序的可扩展线程池)。
使用它是因为创建线程要花费昂贵的资源和时间,如果任务来了才创建线程那么响应时间会变长,而且一个进程能创建的线程数有限。
为了避免这些问题,在程序启动的时候就创建若干线程来响应处理。
🍡9、什么是死锁,如何避免死锁?
死锁一般出现在多线程编程中,当两个线程等待对方获取的锁时,由于各自无法继续执行释放自身的锁而导致的无限等待情况,
程序通常表现为假死。
那么如何避免死锁呢?
1、让程序每次至多只能获得一个锁。当然,在多线程环境下,这种情况通常并不现实
2、设计时考虑清楚锁的顺序,尽量减少嵌在的加锁交互数量
3、既然死锁的产生是两个线程无限等待对方持有的锁,那么只要等待时间有个上限不就好了。
当然synchronized不具备这个功能,但是我们可以使用Lock类中的tryLock方法去尝试获取锁,
这个方法可以指定一个超时时限,在等待超过该时限之后变回返回一个失败信息
🍾10、写出几条你遵循的多线程最佳实践
1、给线程起个有意义的名字,方便调试和查找错误。
2、避免锁定和缩小同步的范围(一个很大的同步范围会让线程效率大幅降低)
3、使用并发集合少用同步集合,例如能用ConcurrentHashMap则不用Hashtable。