您的位置:首页 > 职场人生

面试中的一些问题——JAVA(三)

2016-03-17 22:20 246 查看
22. 线程同步的方法:sychronized、lock、reentrantLock等

在并发量比较小的情况下,使用synchronized是个不错的选择,但是在并发量比较高的情况下,其性能下降很严重,此时ReentrantLock是个不错的方案。

1、ReentrantLock 拥有Synchronized相同的并发性和内存语义,此外还多了 锁投票,定时锁等候和中断锁等候

线程A和B都要获取对象O的锁定,假设A获取了对象O锁,B将等待A释放对O的锁定,

如果使用 synchronized ,如果A不释放,B将一直等下去,不能被中断

如果 使用ReentrantLock,如果A不释放,可以使B在等待了足够长的时间以后,中断等待,而干别的事情

ReentrantLock获取锁定与三种方式:
a) lock(), 如果获取了锁立即返回,如果别的线程持有锁,当前线程则一直处于休眠状态,直到获取锁

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

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

d) lockInterruptibly:如果获取了锁定立即返回,如果没有获取锁定,当前线程处于休眠状态,直到或者锁定,或者当前线程被别的线程中断

2、synchronized是在JVM层面上实现的,不但可以通过一些监控工具监控synchronized的锁定,而且在代码执行时出现异常,JVM会自动释放锁定,但是使用Lock则不行,lock是通过代码实现的,要保证锁定一定会被释放,就必须将unLock()放到finally{}中

3、在资源竞争不是很激烈的情况下,Synchronized的性能要优于ReetrantLock,但是在资源竞争很激烈的情况下,Synchronized的性能会下降几十倍,但是ReetrantLock的性能能维持常态;

23. 锁的等级:对象锁、类锁

假设我有一个类ClassA,其中有一个方法synchronized methodA(),那么当这个方法被调用的时候你获得就是对象锁,但是要注意,如果这个类有两个实例,比如:ClassA a = new ClassA();ClassA b = new ClassA();那么如果你在a这对象上调用了methodA,不会影响b这个对象,也就是说对于b这个对象,他也可以调用methodA,因为这是两对象,所以说对象锁是针对对象的。而类锁,其实没有所谓的类锁,因为类锁实际上就是这个类的对象的对象锁,还是举例,我有一个类ClassA,其中有一个方法synchronized
static methodA(),注意这个方法是静态的了,那就是说这个类的所有的对象都公用一个这个方法了,那如果你在这个类的某个对象上调用了这个方法,那么其他的对象如果想要用这个方法就得等着锁被释放,所以感觉就好像这个类被锁住了一样。

24. 写出生产者消费者模式

25. ThreadLocal的设计理念与作用(还不太懂)

ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是thread local variable(线程局部变量)。它的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。从线程的角度看,就好像每一个线程都完全拥有该变量。

该类有1个默认构造函数,4个普通函数

T get() 返回此线程局部变量的当前线程副本中的值。

protected T initialValue() 返回此线程局部变量的当前线程的“初始值”。 该方法返回当前线程在该线程局部变量的初始值,这个方法是一个延迟调用方法,在一个线程第1次调用get()或者set(Object)时才执行,并且仅执行1次。

void remove() 移除此线程局部变量当前线程的值。

void set(T value) 将此线程局部变量的当前线程副本中的值设置为指定值。

26. ThreadPool用法与优势

合理利用线程池能够带来三个好处:

第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。

第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。

第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

使用:(以下为个人理解)

1.首先创建一个线程池,创建线程池有4种方法 ExecutorService
mThreadPool

Excutors.newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

newFixedThreadPool
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

newScheduledThreadPool
创建一个定长线程池,支持定时及周期性任务执行。

newSingleThreadExecutor
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

2.创建任务队列,将要执行的任务加入其中,通过轮询线程去除,让线程池去执行。LinkedList<Runnable>
mTaskQueue;

3.创建轮询线程PoolThread,对线程池中的任务进行轮询,通过其Handler发消息给线程池去执行任务

4.创建轮询线程用的Handler

Executor是一个顶层接口,在它里面只声明了一个方法execute(Runnable),返回值为void,参数为Runnable类型,从字面意思可以理解,就是用来执行传进去的任务的;
然后ExecutorService接口继承了Executor接口,并声明了一些方法:submit、invokeAll、invokeAny以及shutDown等;
抽象类AbstractExecutorService实现了ExecutorService接口,基本实现了ExecutorService中声明的所有方法;
然后ThreadPoolExecutor继承了类AbstractExecutorService。
在ThreadPoolExecutor类中有几个非常重要的方法:
execute():ThreadPoolExecutor的核心方法,通过这个方法可以向线程池提交一个任务,交由线程池去执行
submit():在ExecutorService中声明的方法,在AbstractExecutorService就已经有了具体的实现,在ThreadPoolExecutor中并没有对其进行重写,这个方法也是用来向线程池提交任务的,但是它和execute()方法不同,它能够返回任务执行的结果,去看submit()方法的实现,会发现它实际上还是调用的execute()方法,只不过它利用了Future来获取任务执行结果。
shutdown();shutdownNow():用来关闭线程池的

27. Concurrent包里的其他东西:ArrayBlockingQueue、CountDownLatch等等

障栅:CyclicBarrier.当所有等待的线程到达障栅后,才能继续向下运行。如一组数拆分n组排序,则要等这n组拍完后再合并,则每部分都排好了,可并行执行。

适用于线程数固定的情况。CyclicBarrier(int parties)其中parties为需要等待的线程个数。可循环使用。

倒计时门阀:CountDownLatch(int count),带计数开关的门,只有在门前等待的线程达到一定数量,门才会打开,线程才会执行。

count为初始值,线程调用await方法等待,方法countDown会导致计数值递减,计数值为0,所有在倒计时门阀范围内等待的线程的阻塞状态将解除。

与障栅不同点:1.不是所有线程都需要等待门阀打开;

2.门阀可由外部事件打开;

3.倒计时门阀是一次性的,一旦计数器为0,就不能再重复用它了。

信号量:一个信号量管理了一个许可集合。Semaphore(int permits),Semaphore(int permits,boolean fair),通过acquire获取一个许可,release释放一个许可。ImageLoader中就用到了信号量控制。

同步队列:SynchronousQueue.是一个没有数据缓冲的阻塞队列,在同步队列上的插入操作必须等待相应的删除执行完成后才能执行。不能调用peek方法来查看队列中是否有数据元素,也不允许对整个队列进行迭代遍历。

交换器:

阶段化处理:

28. wait()和sleep()的区别

wait(),调用一般形式 对象名.wait(),通常需要放入方法synchronize修饰的语句块或方法中。

作用是把当前对象放入对象的等待集合中。

sleep是线程被调用时,占着cpu去睡觉,其他线程不能占用cpu,os认为该线程正在工作,不会让出系统资源。

29. foreach与正常for循环效率对比

使用foreach的对象必须实现Iterator 接口,对iterator进行了更多操作,效率相比fo更低。

30. Java IO与NIO
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: