1、说说进程和线程,以及线程的生命周期?
进程:进程是系统中正在运行的程序,一个程序开始运行就代表开始了一个进程,所以说进程就是程序运行的实例。线程:线程是进程运行时的实例,一个正在运行的进程至少要有一个线程,也可以有多个,一起并行完成一个进程任务。对于单核心系统来说,即使使用多线程,在不可分割的单位时间内也只有一个线程在运行,使用多线程,便会导致线程的频繁切换对于多核心系统来说,多个线程可以并行运行,大大缩短一个进程处理任务的时间,多线程可以更充分利用多核心。
线程的生命周期:
1、新建(New):线程被创建但还没有开始运行,此时线程处于新建状态。此时仅仅是个对象。2、就绪(Runnable):调用的线程的start()方法后,线程被启动并进入就绪状态,等待CPU调度执行。此时,线程已经分配了所有需要的资源,包括堆栈和CPU时间片等。线程进入就绪状态,JAVA虚拟机会为其创建方法调用栈和程序计数器。线程的执行是由底层平台控制, 具有一定的随机性。3、运行(Running):线程被调度执行后,进入运行状态,开始执行run()方法中的代码。4、阻塞(Blocked):当线程需要等待某些操作完成时,比如等待I/O操作或等待某个锁的释放,sleep(),wait(),join()等则进入阻塞状态。此时,线程将不会消耗CPU时间片,直到等待的操作完成。5、终止(Terminated):线程执行完所有代码或发生异常时,进入终止状态。此时,线程释放所有资源,包括堆栈和CPU时间片等。
如何终止一个线程:
1、可以用interrupt()和isInterrupted()、interrupted()方法来停止线程,interrupt()方法并不会真的停止一个线程,它只是将对应的线程打上true的中断标记,isInterrupted()方法可以返回线程的中断标记状态,根据状态来处理对应的代码。2、interrupted()也可以返回中断标记状态,方法底层调用的是isInterrupted()方法,但interrupted()是一个静态方法,最好用在当前线程上,而且一旦调用了interrupted()方法之后,还会立刻清除中断标记状态。3、利用中断异常也可以停止线程,例如catch(InterruptedException e),然后调用interrupt()方法,也可以终止一个线程。
2、说说volatile、synchronized、ThreadLocal?
Volatile
多线程通信的关键字,常见于Atomic原子类value属性的修饰符、ConcurrentHashMap里HashEntry、Node内部类的value、next属性的修饰符。1、保证在多线程运行对共享变量的 可见性。即每一个线程在自己的 工作内存 中对公共变量的修改,都会被强制刷新回 主内存。注意,volatile只保证 可见性 ,但不保证 原子性。2、禁止指令重排。即编译器和处理器会对指令重排序以提高运行性能,但不会对存在依赖的指令进行重排序,单线程下重排序可以保证最终执行的结果与程序顺序执行的结果一致,但是在多线程下就会存在问题。而volatile就是对修饰的属性在读、写时,在内存中插入一个内存屏障,相当于告诉CPU和编译器先于这个命令的必须先执行,后于这个命令的必须后执行,经典的用法就是双重检查锁。普通的单例模式在单程环境是没有问题的,但在多线程环境下,不加锁会创建多个对象实例,从而违背单例原则,所以用双重锁来判断是否需要实例和初始化;其次,如果没有volatile修饰,对象在线程一未完全初始化完成就被线程二使用,可能会抛出初始化未完成异常,例如空指针等。
synchronized
ThreadLocal
3、说说CountDownLatch、CyclicBarrier 、Semaphore?
4、说说synchronized锁升级过程?
5、说说synchronized和Lock锁的区别?
6、说说线程池?
7、新建 T1、T2、T3 三个线程,如何保证它们按顺序执行?
8、多线程之间如何进行通信?
9、Fork/Join 框架是干什么的?
10、FutureTask 是什么?