1. 什么是线程?java
线程是操做系统中运算调度的最小单位,算法
包含在进程中;数据库
使用多线程在处理密集任务的时候能够提速。Java语言对多线程提供了很好的支持。编程
2. 线程和进程的区别?缓存
一个进程能够有不少线程,每条线程执行不一样的任务。安全
不一样进程有不一样的内存空间,全部的线程共享一块内存空间。性能优化
每一个线程都有单独的栈内存存储本地数据。服务器
3. 线程的实现方式?多线程
继承Thread类,调用Runnable接口;架构
Java继承的单根性,实现Runnable接口,重写run()方法实现线程。
4. Start和Run的区别?
Start启动新建立的线程,start内部调用run方法;
直接调用run方法,只会在原来的线程中调用,没有新的线程启动,start方法会启动新线程。
5. Runable和Callable有什么不一样?
Runnable从jdk1.0就开始有的,Callable是jdk1.5增长的;
Callable的call()方法能够有返回值和抛出异常,Runnable的run()方法没有这些功能;
Callable还能够返回装载有计算结果的Future对象。
6. Java的内存模型?
Java的内存模型规定和指引了java程序在不一样的内存架构,CPU和操做系统之间有肯定性的行为;
它们在多线程的状况下尤为重要,内存模型为多线程之间的可见性提供了保证;
内存模型中有一块共享的内存空间——主内存,持有全部线程的共享变量,各个线程的的本地内存持有的仅是共享变量的副本;
当线程A发生变化的时候,将副本信息刷新到主内存中;线程B在主内存中读取线程A改变的信息。
7. volatile变量是什么?
在并发编程中缺乏同步的状况下,多线程对成员变量的操做是透明的,其它线程可见;
vlatile能够保证下一个读取操做会在前一个写操做以后发生,只有成员变量才能使用它。
8. 什么是线程安全?Vector是一个线程安全类么?
多线程状况下,同时执行一段代码,运行结果和单线程保持一致,就是线程安全;
Vector是用同步方法来实现线程安全的;ArrayList不是线程安全的;
9. Java中的竞态条件?例子
多线程对一些资源的竞争,首先要执行的程序竞争失败从新排队,致使整个流程没有按照预期的顺序处理,出现一些不肯定的,很难发现的bug,这种状况是竞态条件;
例如:无序处理
10. Java中如何中止一个线程?
没有中止线程的API;
JDK1.0提供,stop(),suspend(),resume()等控制线程的方法,已经被被弃用,太暴力;
当run()或者call()方法执行完以后线程会自动结束;
手动结束,能够调用interrupt()来中断线程,有一个中断标志。
11. 一个线程发生异常时会怎样?
没有捕获线程会中止执行,抛异常UncaughtExceptionHandler;
JVM内部提供了Thread.getUncaughtExceptionHandler()来查询线程是否设置异常处理。
12. 如何实现两个线程之间共享数据?
能够经过共享对象来实现;
13. Notify和NotifyAll的区别?
Notify()唤醒单个线程;
notifAll()唤醒全部的线程,让他们争夺锁。
14. 为何wait,notify,notifyall这些方法不在thread类里面?
这些方法防治Object类里面;
由于java提供的锁是对象级的锁,而不是线程级的锁,每一个对象都有锁,经过线程得到;
定义在Thread里面,不符合对象锁的设计。
15. 什么是ThreadLocal变量?
本地线程变量;
让每个线程都有ThredLocal,竞态条件就被消除;
对于频繁建立对象的线程,使用它能够减小对象的建立个数,在线程本地内存中持有变量副本,不用每次都建立;
例如:使用ThreadLocal可让SimpleDateFormat变成线程安全的;
16. Interrupted和isInterrupted方法的区别?
前者会将中断状态清除,后者不会;
Java多线程中的中断机制是用内部标识来实现的,调用interrupt来中断一个线程会设置一个中断标志true,查询中断状态的时候,标志会被清除;
后者用来查询中断状态不会改变中断状态标志;
前者是静态的,后者是非静态的;
17. 为何wait和notify方法要在同步代码块中调用?
强制要求的,不这样作会抛异常IllegalMonitorStateException;
避免两者之间产生竞态条件;
18. Java中的同步集合与并发集合的区别?
同步集合与并发集合都为对线程提供了合适的线程安全的集合,并发集合扩展性更高;
Java5以前,只有同步集合,且在多线程并发的时候会致使争抢,阻碍看程序的扩展性;
Java5以后,出现并发集合,例如ConcurrentHashMap,不只提供线程安全,还用锁分离和内部分区等,扩展性更好。
19. Java中堆和栈有什么不一样?
栈是一块和线程紧密相关的内存区域,每一个线程都有本身的栈内存,用于存储本地变量,方法参数和栈调用,一个栈中存储的变量对其它线程不可见;
堆是全部线程共享的一片公共内存区域,对象都在堆中建立;
为了提高效率,线程会从堆中弄一个缓存到本身的栈;
在多线程状况下,从公共内存中读取变量存在线程不安全问题,使用volatile变量能够保证线程安全。
20. 什么是线程池?为何要使用它?
建立若干数量的线程来等待响应处理,就叫线程池,线程池里面的线程叫工做线程;
Java API提供了Execution框架能够建立不一样的线程池;
Why?
建立线程须要花费昂贵的资源和时间,任务来了在建立的话响应时间就会变长,影响效率;
能够建立单线程池,每次处理一个任务;
能够建立固定数量的线程池,或者可扩展的线程池来处理 多任务;
比喻:公交场
21. 如何解决生产者消费者问题?
一个线程生产任务,提供给其它线程进行消费 ,这就是属于生产者消费者模型;
生产者消费者问题,能够经过线程之间的通信来解决,java API提供了wait和notify方法来解决这个问题;
更好的方法是Semaphore或者BlockingQueue来实现生产者消费者模型。
22. 如何避免死锁?
死锁是两个或两个以上的进程在执行的时候,争夺资源形成相互等待,程序卡死的一种现象;
死锁的发生存在下面四个条件:
互斥条件,一个资源每次只能被一个进程调用;
请求与保持条件,一个进程得到资源阻塞时,对已经得到的资源保持不放;
不剥夺条件,进程已经得到资源,在未使用完成以前,不强行剥夺;
循环等待条件,进程之间头尾相接等待资源释放;
避免死锁就是阻止循环等待条件,将系统中的全部资源设置标志位,排序,规定全部的进程在申请资源的时候按顺序执行(升序或降序);
23. Java中活锁和死锁的区别?
活锁,就是进程的状态能够改变,可是不可以执行; 例如,走廊里两我的相遇,一个让一个,一直让不开的现象。
死锁,就是进程的状态不能改变,也不可以执行; 例如,走廊里两我的相遇,堵在那儿不动的现象。
24. 怎样检查一个线程是否拥有锁?
Java.lang.Thread中有一个方法holdsLock(),返回true,当前线程持有锁;
25. Java中synchronized和RentrantLock有什么不一样?
它们都是锁;
使用synchronized关键字做为锁来实现互斥,它能够锁方法,锁语句块,锁对象,可是不可以扩展锁以外的方法或者边界,尝试获取锁时候中途不能取消等;
Java5以后的lock接口提供了更为复杂的控制来解决并发问题;
RentrantLock类实现了Lock,它拥有synchronized相同的并发性和内存语义且扩展性更好。
26. 有3个线程,怎样保证他们按照顺序执行?
有不少种方法;
可使用join()方法在一个线程中启动另外一个线程,
好比:A,B,C三个线程;将A join到b中,b join到c中,先启动C线程,按照c-b-a的顺序执行;
27. Thread类中的yield方法有什么做用?
能够暂停当前正在执行的线程对象,让优先级高的先执行;
它是一个静态方法,保证当前线程放弃CPU占用,而不保证优先级高的就必定执行,有可能线程刚暂停又立马恢复;
28. Java中的ConcurrentHashMap的并发度是什么?
ConcurrentHashMap把实际的map划分为若干部分来实现它的可扩展性和线程安全;
这种划分是使用并发度得到的,它是ConcurrentHashMap类构造函数的一个构造参数,默认值是16,这样能在多线程状况下避免争用。
29. 若是你提交任务时候,线程池已经满,会发生什么?
会抛异常RejectedExecutionException;由于在非扩展线程池的状况下该线程任务不可以被调度。
30. Java中线程池中的submit和execute方法有什么区别?
两个方法均可以向线程池提交任务;
execute方法的返回值类型是void,定义在Execotor接口中;
Submit方法返回持有计算结果的future对象,它定义在ExecutorService接口中,它扩展了Exector接口;
其它的线程池类ThreadPoolExecutor和ScheduledThreadPoolExecutor都有这些方法;
31. 什么是阻塞式方法?
指程序会等待该方法完成,期间不会作其它的事情;
ServerSocket类的accept方法就是阻塞式方法,会一直等待客户端链接;
阻塞指的是线程在调用结果返回以前,当前线程会被挂起,直到获得结果以后才会返回;
32. Java中的ReadWriteLock是什么?
读写锁,用来提高并发程序性能;
Java5 新增的接口,一个读写锁维护一对关联的锁,一个用于读操做,一个用于写操做;
读锁是共享的,写锁是独占的。
33. 多线程中的忙循环是什么?
忙循环就是开发者用空循环让一个线程等待,一直持有CPU的控制;
不像wait(),sleep(),yield()等方法,放弃了CPU的控制;
好处是保留CPU缓存,减小线程等待,避免重建缓存。
34. 若是同步块内的线程抛出异常会发生什么?
线程会释放锁;
35. 单例模式的双检锁是什么 ?
它是用来建立线程安全的,写单例模式的老方法;
当单例实例第一次被建立时候它试图用单个锁进行性能优化,可是因为太过复杂几乎没人用。
36. 如何在java中建立线程安全的singleton?
双检索实现单例;
也能够经过JVM的类加载和静态变量初始化特征来建立单例;
或者利用枚举实现;
以上三种都是线程安全的可用的;
37. 写出3条你遵循的多线程最佳实践?
1)给线程起一个有意义的名字
方便找bug或追踪线程执行;
2)避免锁定和缩小同步范围
锁花费的代价高昂,且上下文切换更耗费时间和空间,最低限度的使用同步锁,缩小临界区,有利于提高性能。
3)多用同步类,少用wait和notify
CountDownLatch, Semaphore, CyclicBarrier 和 Exchanger 等这些同步类简化了编码操做;
而wait和notify很难实现相对复杂控制流控制;
使用高级的同步工具备利于优化线程;
4)多用并发集合少用同步集合
并发集合比同步集合扩展性好
38. 如何强制启动一个线程?
线程是被线程 调度器控制的,java中没有提供响应的API。
39. Java多线程中调用wait和sleep的方法有什么不一样?
均可以让线程进入等待状态;
wait方法用于线程间通讯,若是等待条件为真且其它线程被唤醒是它会释放锁;
sleep方法仅仅是释放CPU的资源,让当前线程中止执行,不会释放锁;
CyclicBarrier和CountDownLatch均可以让一组线程等待其它线程;
不一样点是CountdownLatch不能从新使用。
2. 什么是FutureTask?
在java并发编程中,FutrueTask表示一个能够取消的异步运算;
它有启动运算,取消运算,查询运算,取回运算等方法,只有单运算完成才能取回结果,运算未完成get将会被阻塞。
异步运算也是调用Runnable接口,能够交给Executor来执行。
3. 为何应该在循环中检查等待条件?
处在等待状态的线程可能会收到错误报警和伪唤醒,不在循环中检查等待,程序就会在没有知足条件的状况下退出;
当一个线程被notify时候,并不认为它原来的状态仍然有效,由于这段时间它有可能改变。
4. 如何在java中获取线程堆栈?
JVM会把全部线程的状态存到日志文件,或者输出到控制台;
Windows中Ctrl+Break组合键获取;
Linux下用kill -3 命令获取;
业能够用jps这个工具找到id;
5. JVM中的那个参数是用来控制线程的栈堆大小的?
-Xss用来控制线程栈堆大小;
6. Java中的semaphore是什么?
是一种新的同步类,是一个计数信号;
信号量维护了一个许可集合,未经许可的线程请求会被阻塞,得到许可请求才能够进入排队状态;
Semaphore只对可用许可的信号进行计数;
信号量经常使用在多线程代码种,好比数据库链接池等
7. Swing是线程安全的么? 为何?
不是线程安全的;
由于swing的提供的组件不能再多线程中进行修改,全部对GUI组件的更新都须要在AWT线程中完成;
而swin提供了同步和异步两种回调方法来进行更新;
8. Java中的invokeAndWait和invokeLater方法有什么区别?
做用都是从当前线程更新GUI组件;
前者同步更新GUI组件,好比一个进度条,一旦更新了,进度条就要作出相应改变;
后者请求派线程更新组件,好比一个进度条,一旦更新,并无更新,须要等待派发线程完成更新,才最终更新。
9. Swing API中的哪些方法是线程安全的 ?
Swing不是线程安全的,它的一些方法是线程安全的;
好比:repaint(),revalidata(),JTextComponent的setText()方法和JTextArea的insert()方法和append()方法等。
10. Java中volatile变量和atomic变量有什么不一样?
Java中的volatile变量能够确保先行关系,写操做会发生在后续的读操做以前,可是并不能保证原子性;
例如用volatile修饰count变量,那么count++操做就不是原子性的;
AtomicInteger类提供的atomic方法可让这种操做具备原子性;
11. Java中的fork join框架是什么 ?
Fork join框架是JDK7出现的一款工具,java开发人员能够经过它,充分利用现代服务器上的多出来器;
能够将全部可用的处理能力调用起来提高程序性能;
它使用了工做窃取算法,能够完成更多任务的工做线程,能够从其它线程中窃取任务来执行。