一个很明显的原因是JAVA提供的锁是对象级的而不是线程级的,每个对象都有锁,通过线程获得。由于wait,notify和notifyAll都是锁级别的操作,所以把他们定义在Object类中因为锁属于对象。
45、什么是ThreadLocal变量?
ThreadLocal是Java里一种特殊的变量。每个线程都有一个ThreadLocal就是每个线程都拥有了自己独立的一个变量,竞争条件被彻底消除了。它是为创建代价高昂的对象获取线程安全的好方法,比如你可以用ThreadLocal让SimpleDateFormat变成线程安全的,因为那个类创建代价高昂且每次调用都需要创建不同的实例所以不值得在局部范围使用它,如果为每个线程提供一个自己独有的变量拷贝,将大大提高效率。首先,通过复用减少了代价高昂的对象的创建个数。其次,你在没有使用高代价的同步或者不变性的情况下获得了线程安全。
46、Java中interrupted 和 isInterrupted方法的区别?
interrupt interrupt方法用于中断线程。调用该方法的线程的状态为将被置为”中断”状态。 注意:线程中断仅仅是置线程的中断状态位,不会停止线程。需要用户自己去监视线程的状态为并做处理。支持线程中断的方法(也就是线程中断后会抛出interruptedException的方法)就是在监视线程的中断状态,一旦线程的中断状态被置为“中断状态”,就会抛出中断异常。
interrupted 查询当前线程的中断状态,并且清除原状态。如果一个线程被中断了,第一次调用interrupted则返回true,第二次和后面的就返回false了。
isInterrupted 仅仅是查询当前线程的中断状态
47、为什么wait和notify方法要在同步块中调用?
Java API强制要求这样做,如果你不这么做,你的代码会抛出IllegalMonitorStateException异常。还有一个原因是为了避免wait和notify之间产生竞态条件。
48、为什么你应该在循环中检查等待条件?
处于等待状态的线程可能会收到错误警报和伪唤醒,如果不在循环中检查等待条件,程序就会在没有满足结束条件的情况下退出。
49、Java中的同步集合与并发集合有什么区别?
同步集合与并发集合都为多线程和并发提供了合适的线程安全的集合,不过并发集合的可扩展性更高。在Java1.5之前程序员们只有同步集合来用且在多线程并发的时候会导致争用,阻碍了系统的扩展性。Java5介绍了并发集合像ConcurrentHashMap,不仅提供线程安全还用锁分离和内部分区等现代技术提高了可扩展性。
50、什么是线程池? 为什么要使用它?
创建线程要花费昂贵的资源和时间,如果任务来了才创建线程那么响应时间会变长,而且一个进程能创建的线程数有限。为了避免这些问题,在程序启动的时候就创建若干线程来响应处理,它们被称为线程池,里面的线程叫工作线程。从JDK1.5开始,Java API提供了Executor框架让你可以创建不同的线程池。
51、怎么检测一个线程是否拥有锁?
在java.lang.Thread中有一个方法叫holdsLock(),它返回true如果当且仅当当前线程拥有某个具体对象的锁。
52、你如何在Java中获取线程堆栈?
kill -3 [java pid] 不会在当前终端输出,它会输出到代码执行的或指定的地方去。比如,kill -3 tomcat pid, 输出堆栈到log目录下。
Jstack [java pid] 这个比较简单,在当前终端显示,也可以重定向到指定文件中。 -JvisualVM:Thread Dump 不做说明,打开JvisualVM后,都是界面操作,过程还是很简单的。
53、JVM中哪个参数是用来控制线程的栈堆栈小的?
-Xss 每个线程的栈大小
54、Thread类中的yield方法有什么作用?
使当前线程从执行状态(运行状态)变为可执行态(就绪状态)。
当前线程到了就绪状态,那么接下来哪个线程会从就绪状态变成执行状态呢?可能是当前线程,也可能是其他线程,看系统的分配了。
55、Java中ConcurrentHashMap的并发度是什么?
ConcurrentHashMap把实际map划分成若干部分来实现它的可扩展性和线程安全。这种划分是使用并发度获得的,它是ConcurrentHashMap类构造函数的一个可选参数,默认值为16,这样在多线程情况下就能避免争用。
在JDK8后,它摒弃了Segment(锁段)的概念,而是启用了一种全新的方式实现,利用CAS算法。同时加入了更多的辅助变量来提高并发度,具体内容还是查看源码吧。
56、Java中Semaphore是什么?
Java中的Semaphore是一种新的同步类,它是一个计数信号。从概念上讲,从概念上讲,信号量维护了一个许可集合。如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。每个 release()添加一个许可,从而可能释放一个正在阻塞的获取者。但是,不使用实际的许可对象,Semaphore只对可用许可的号码进行计数,并采取相应的行动。信号量常常用于多线程的代码中,比如数据库连接池。
57、Java线程池中submit() 和 execute()方法有什么区别?
两个方法都可以向线程池提交任务,execute()方法的返回类型是void,它定义在Executor接口中。