并发基础一
http://www.importnew.com/12773.html
1.什么是线程安全
多个线程访问某个类,主调代码不需要额外的同步和协同,这个类就能表现出正确的行为,我们就成这个类是线程安全的。比如LinkedBlockingQueue
使用Lock
加锁保证任何;
2.什么是线程
线程是操作系统能够进行运算调度的最小单位(我的理解是计算机有几个核心就可以并行运行几个线程);
3.什么是竞态条件
在并发编程中由于各个线程不正确的执行时序(执行时间顺序)而导致的不正确的结果,叫做竞态条件(race condition)。最常见的竞态条件是“先检查后执行”操作,即通过一个可能失效的观察决定下一步执行的动作。 如下代码会在condition
上产生竞态条件:
thread1:
synchronized(sharedMonitor){
//setup condition for thread2
sharedMonitor.notify();//等待sharedMonitor对象监视器的线程被唤醒;
}
thread2:
while(condition){
//重要X:线程调度器可能再次切换线程;
synchronized(sharedMonitor){
sharedMonitor.wait();
}
}
- 正确的做法是在thread2中将
while(condition)
放进同步代码块;
4. 如何停止一个线程
- 通过使用volatile布尔变量退出
run()
方法的循环——所有线程公用此变量,而且对此变量的修改可以被立即被各个线程的run()
方法感知; - ExecutorService 类的
shutdownnow()
方法;
5. 线程运行时发生异常会怎样
如果不捕获异常的话线程将会停止执行,并且将**异常信息和线程交给默认的UncaughtExceptionHandler
未捕获异常处理器进行处理。当然可以实现该接口,并且通过方法设置线程对应的“未捕获异常处理器”。
6.线程间如何共享数据——也可以说是如何通信?
7. notify()
和notifyAll()
的区别
前者是唤醒一个等待调用该方法对象说的线程,后者是唤醒所有等待该锁的线程,然后让他们竞争锁。notify()
用不好容易导致死锁。
8.interrupt、interrupted 、isInterrupted
三个方法的区别
interrupt
会将此对象线程的“中断标识”设置为true,标识此线程是可中断的;interrupted
和isInterrupted
都会返回中断标识状态,但是前者会清空中断状态;
9.为什么在循环中检查等待条件
while(condition)
wait();
因为等待状态的线程可能收到错误的警报,这样更加严谨,是的满足条件的条件下在运行后续程序;
10.java中堆heap和栈stack的区别
java堆的
1. 目的是存放几乎所有的对象实例和数组;
2. 在虚拟机启动时创建,被所有线程所共享;
3. 堆内存没有空间完成实例分配且无法在扩展时,抛出OutOfMemoryError异常;
java栈的
1. 存放基本数据类型、对象的引用(、方法参数和栈调用);
2. 局部变量表所需的内存空间在编译期间完成分配。java栈是线程私有的,生命周期与线程相同;
3. 这个区域规定了两种异常:线程请求的栈深度超过虚拟机所允许的深度抛出StackOverflowError。如果动态扩展的虚拟机栈无法申请到足够的内存,则会抛出OutOfMemoryError异常;
11.怎样确保三个线程按照顺序执行
join()
方法:当前线程等待调用此方法的线程对象结束后再执行。
1
Thread b=new Thread(()-> {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread_b finished");
});
Thread a=new Thread(()-> {
try{
b.join();
System.out.println("thread_a wait thread_b 3 second and finished");
}catch (Exception e){
e.printStackTrace();
}
});
a.start();
b.start();
12.如果同步块内的线程抛出异常会发生什么
无论你的同步块是正常还是异常退出的,里面的线程都会释放锁;
13.wait() 和 sleep()方法有什么不同
wait()
会释放锁。sleep()
仅仅是释放CPU资源而不释放锁。
14. ReentrantLock中三个加锁方法的区别
tryLock
能获得锁就返回true,不能就立即返回false,tryLock(long timeout,TimeUnit unit)
,可以增加时间限制,如果超过该时间段还没获得锁,返回falselock
能获得锁就返回true,不能的话一直等待获得锁;- lock和
lockInterruptibly
,如果两个线程分别执行这两个方法,但此时中断这两个线程,前者不会抛出异常,而后者会抛出异常
15.停止线程:做标记,三方法抛异常清除,短方法清除
停止一个线程使用interrupt()
方法
除非线程要中断本身。此操作是为当前线程做标识“可以停止”,而非真正的停止线程。
如果线程在调用wait()、join()、sleep()
及其各种变参多态函数后,再调用interrupt()
方法会清空其interurpted
的状态,并抛出InterruptedException
异常。
线程是否是“可停止状态”可以调用两个方法:
boolean interrupted()
:会清除“可停止状态”,测试的是当前线程;
2.boolean isInterrupted()
:不会清除状态,测试的是Thread对象;
因此中断线程的正确姿势是:
void run(){
while(!Thread.interrupt){
//do work
}
}
当对线程调用 thread.interrupt() 时,就会停止工作,线程中断。注意最外层的try代码块。
16. 关闭线程池
executor.shutdown();//任务队列中的任务仍然被执行完成
while(!executor.isTerminated()){};
return;
...
shutdownNow()会返回未执行完的任务。
17.wait(),wait(XX),sleep(XX),yield()和join()
wait()
:放弃锁和cup时间片,等待其他线程用notifyAll()
唤醒;wait(XX)
:调用notifyAll()
或者到XX时间后开始争用锁对象;sleep(XX)
: 不释放锁,指定时间内放弃cpu时间片;yield()
:同sleep,但是可能释放cup时间片后立即又开始执行,但是cup时间片只会让给线程优先级不小于其的线程;join()/join(XXX)
:通过wait()实现,释放锁;