java多线程之面试题
怎么理解多线程?
1. 让应用程序在一个时间段做多个事情,提高效率
2. 可以实现异步的效果,主线程马上返回成功,子线程继续去工作
程序、进程、线程的关系
一个程序,就有一个进程,一个进程中可以有多个线程,其中又分为主线程和子线程。
理解并发与并行
并发:通过CPU调度算法,让用户看上去同时执行,实际上,是通过CPU在高速切换,并不是真正的额同时
并行:多个CPU实例或者多台机器同时执行一段处理逻辑,这就是真正的同时;
如何创建线程?
1. 继承Thread
2. 实现Runnable接口(优先选择)
注意:
1. 都要重写run()方法
2. 调用thread.start(),线程才真正启动
线程的各种状态
可执行(Runnable):当调用start()方法后,一个线程变为可执行状态,但是并不意味着他会立刻开始真正地执行。而是被放入线程池,由线程调度器根据线程优先级决定何时挂起执行。
执行中(Running):处理器已经在执行线程的代码。他会一直运行直到被阻断,或者通过静态方法Thread.yield()自行放弃执行的机会,考虑到场景切换所带来的开销,yield()方法不应该被经常调用。
等待中(Waiting):线程由于等待I/O等外部进程的处理结果而处于被阻断的状态,调用currObject.wait( )方法会使得当前线程进入等待状态,直到其它线程调用currObject.notify() 或者currObject.notifyAll() 。
睡眠中(Sleeping):重载方法Thread.sleep(milliseconds),Thread.sleep(milliseconds, nanoseconds)可以迫使Java线程进入睡眠状态(挂起)。
由于I/O阻塞(Blocked on I/O):当I/O条件发生变化时(例如读取了几个字节的数据)会迁移到可执行状态。
由于同步阻塞中(Blocked on synchronization): 当获取锁之后会进入执行中状态。
多线程一般怎么用?
线程池,线程池工作原理
为什么要用线程池
1. 对于一些简单的工作,每次创建和销毁线程,比较耗资源
2. 每次创建和销毁线程,也让程序变慢
3. 每个进程的中,可以创建的线程是有限的,为了保护服务器,这也是必须的
Java线程池中submit() 和 execute()方法有什么区别?
两个方法都可以向线程池提交任务,execute()方法的返回类型是void,它定义在Executor接口中, 而submit()方法可以返回持有计算结果的Future对象,它定义在ExecutorService接口中,它扩展了Executor接口,其它线程池类像ThreadPoolExecutor和ScheduledThreadPoolExecutor都有这些方法。
什么是多线程的线程安全
保证共享资源在多线程的情况下不会出现错乱。
如何保证线程安全
synchronized
同步方法、同步类、同步块
缺点:不灵活
Lock
可重入锁
读写锁
1. 多个读同时读,不加锁
2. 多个写互斥
3. 有读有写,写优先,如果读写同时等待,那优先唤醒写
缺点:手动释放锁
同步集合、并发集合
同步集合:HashTable、Vector、Collections中的同步方法
并发集合:ConcurrentHashMap、CopyOnWriteArrayList、CopyOnWriteHashSet
Volatile
不变类
什么时候会出死锁
两个线程同时占有对方要的资源
如:
线程1有资源A,要资源B
线程2有资源B,要资源A
死锁发生的条件:
互斥条件:一个资源每次只能被一个进程使用。
请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
解决方法:
有序资源分配法
银行家算法
如何控制线程
闭锁、栅栏、信号量
join控制线程有序进行
项目中用到哪些
信号量、线程池
如果同步块内的线程抛出异常会发生什么?
无论你的同步块是正常还是异常退出的,里面的线程都会释放锁;至于Lock就要在finally中释放锁
wait()和sleep()的区别
wait() 释放锁,sleep() 不释放锁
wait() 要notify() 或 notifyAll() 才有机会获得锁,sleep() 一段时间后,自动继续
http://www.importnew.com/12773.html