41.创建线程池有哪些方式?
分为ThreadPoolExecutor手动创建程序池和Executors自动创建线程池,具体又分为7种:
newFixedThreadPool():创建固定线程池,控制并发的线程数,超出线程池的线程会在等待列队中。
newCachedThreadPool():创建可缓存的线程池,超出线程池的线程会缓存一会回收,线程池中的线程不够会创建线程。
newSingleThreadExector():创建单个线程的线程池,可保证先进先出的顺序。
newScheduledThreadPool():创建可执行延迟任务的线程池。
newWorkStealingPool():创建抢占式执行的线程池。
ThreadPoolExecutor():手动创建线程池,它创建最多可以设置7个参数。
42.线程池都有哪些状态?
running:这是正常状态,接受新的任务,处理等待队列中的任务。
shutdown:不接受新的任务,但会继续处理等待列队中的任务。
stop:不接受新的任务,不再处理等待列队中的任务,中断正在执行任务的线程。
tidying:所有的任务都销毁了,workCount为0,线程池的状态在转换为tidying状态,会执行钩子方法terminated()。
terminated():线程彻底终止。
43.线程池中submit()和execute()方法有什么?
submit():会执行Runnable和Callable类型的任务。
execute():只会执行Runnable类型的任务。
44.在Java程序中怎么保证多线程的运行安全?
使用安全类,比如Java.util.concurrent下的类。
使用自动锁synchronized.
使用手动锁Lock.
45.多线程中synchronized锁升级的原理是什么?
锁对象里有一个字段threadid
首次访问锁对象时,threadid为空,jvm会将其持有偏向锁,将threadid设置为当前线程的id,再次访问锁对象时会判断threadid与当前id是否一致,如果一致则直接使用对象,如果不一致会把偏向锁升级为轻量级锁,通过自旋循环一定次数获取锁,一定次数后还没有拿到想要的对象,则会把轻量级锁升级会重量级锁。
锁升级的目的:减少锁带来的性能消耗。