# 多线程

**1)Lock和synchronized的区别**

ReentrantLock获取锁的三种方式

1\)lock(),如果获取到了锁立刻返回,如果别的线程持有锁,当前线程一直处于休眠状态,直到获取锁

2\)tryLock(),如果获取锁立即返回true,如果别的线程正持有锁,立即返回false;

3\)tryLock(long timeout, TimeUnit unit),如果获取到锁立即返回true,如果别的线程正持有锁,会等待给定的时间,在等待的过程中,如果获取到了锁,就返回true,如果等待超时,返回false;

4\)lockInterruptibly:如果获取了锁立刻返回,否则处于休眠状态,知道获取锁或者是被别的线程中断

使用synchronized,如果A不释放锁,则B只能一直等待下去,反之,ReentrantLock则是可以在等待一段时间后中断等待.

synchronized是在JVM层面上的,因此如果程序出现异常会自动释放锁,而ReetrantLock则需要手动释放锁.

**2)什么是线程安全**

多线程访问同一段代码不会出现不确定的结果.线程安全需要通过同步来实现,线程安全都是由全局变量和静态变量引起的.

**3)线程死锁的原因,如何避免线程死锁的发生**

A)系统资源的竞争

B)进程推进顺序非法,P1--A,P2--B,如果此时P1请求B,P2请求A则可能发生死锁

避免死锁:

1.加锁的顺序,保证所有的线程都是按照相同的顺序加锁的

2.加锁时限(线程加锁的时候加上一定的时限,超过时限则放弃该锁的请求,并释放自己的锁)

3.死锁的检测

检测到死锁后的处理方法:

1.释放所有的锁,等待一段时间后重新请求资源

2.给线程设置优先级,让一部分线程优先获取的锁

**4)CountDownLatch和CyclicBarrier以及Semaphore用法**

<http://www.importnew.com/21889.html>

**5)线程池**

newSingleThreadPool:创建一个单一的线程池,先进先出的方式处理任务

newCachedThreadPool:创建一个可缓存的线程池,线程池的大小是可以随着改变的.自动创建新的线程,个数的无限制的

newScheduleThreadPool:定长的线程池,支持定时和周期性的任务执行.

newFixedThreadPool:定长的线程池,可以控制线程最大的并发数,超过的线程在队列中等待.

线程池的submit方法有返回值.

shutdown:线程池的状态变为shutdown,此时不能再向线程池中添加线程,如果添加会抛出异常.

shutdownNow:立刻停止线程池中的正在执行的线程并不再处理队列中尚未处理的线程返回未处理的线程

**6)线程池的工作原理**

线程池创建的Thread对象的run方法会获取阻塞队列中的一个Runable对象,然后执行Runable对象中的run()方法,在执行完Runable对象的run方法后,Thread继续从阻塞队列中获取下一次Runable对象.这样就避免了创建新的线程的过程.

这其中有线程池大小的动态调整,阻塞队列的策略等
