@wxf
2018-07-31T09:23:18.000000Z
字数 3252
阅读 858
面试系列
线程是进程内的一个执行单元。
计算机中正在运行的每一个程序都是一个进程,如下图:
线程被创建启动后,并不是直接进入执行状态,也并不是一直处于执行状态。
线程的生命周期分为创建、就绪、执行、阻塞、死亡5种状态。
# 新建线程
new Thread(new Runnable() {
public void run() {
System.out.println("线程" + Thread.currentThread() + "执行完毕");
}
}).start();
一般分为两种
run()方法是线程的执行体,不能由我们手动调用。
start()方法的作用是启动线程,执行start()方法后系统会把run()方法当成线程的执行体来运行。而且不能多次启动一个线程,如果多次调用会产生:IllegalThreadStateException异常。
要理解volatile作用首先要理解Java内存模型,volatile关键字的作用主要有两点:
Java内存模型定义了一种多线程访问Java内存的规范。Java内存模型要完整讲不是这里几句话能说清楚的,我简单总结一下Java内存模型的几部分内容:
synchronized是一个Java的关键字,Lock是一个接口;
synchronized代码块执行完或线程抛出异常时结束线程,Lock必须要显示调用释放锁的方法:unlock();
synchronized是不可中断锁,Lock是可中断锁;
synchronized无法判断锁的状态,Lock可以判断锁的状态;
synchronized是非公平锁,而Lock可以设置为公平锁。
如果你的代码在多线程下执行和在单线程下执行永远都能获得一样的结果,那么你的代码就是线程安全的。
线程安全也是有几个级别的:
如果这个异常没有被捕获的话,这个线程就停止执行了,即后面的代码不会被执行了 ;但是如果这个异常被捕获了,该线程不会停止运行,即后面的代码依然会被执行。另外重要的一点是:线程停止执行后,如果这个线程持有某个某个对象的监视器,那么这个对象监视器会被立即释放
sleep()和wait()都可以用来放弃CPU的执行权
sleep()是线程Thread的方法,而wait()是Object对象的方法;
sleep()不会释放对象锁,wait()会释放;
sleep()可以在任意地方使用,wait()只允许在同步方法或同步块中使用
这是JDK强制的,wait()方法和notify()/notifyAll()方法在调用前都必须先获得对象的锁
区别在于:wait()方法立即释放对象监视器;notify()/notifyAll()方法则会等待线程剩余代码执行完毕才会放弃对象监视器。
避免频繁地创建和销毁线程,达到线程对象的重用。另外,使用线程池还可以根据项目灵活地控制并发的数目。
简单说ThreadLocal就是一种以空间换时间的做法,在每个Thread里面维护了一个以开地址法实现的ThreadLocal.ThreadLocalMap,把数据进行隔离,数据不共享,自然就没有线程安全方面的问题了
ConcurrentHashMap的并发度就是segment的大小,默认为16,这意味着最多同时可以有16条线程操作ConcurrentHashMap,这也是ConcurrentHashMap对Hashtable的最大优势。
线程A和线程B相互等待对方持有的锁导致程序无限死循环。
首先要说的是单例模式的线程安全意味着:某个类的实例在多线程环境下只会被创建一次出来。单例模式有很多种的写法,我总结一下:
JAVA线程池的分析和使用
Java线程池与五种常用线程池策略使用与解析
Java多线程:线程池
理解线程池的原理