1.为什么用线程池:
有时候,系统需要处理非常多的指定时间很短的请求,如果每个请求都开启一个新线程,系统就不断增加线程的创建和销毁,有时花在创建和销毁线程上的时间就会比线程执行的时间还长。
而且当线程数量太多,系统不一定能受得了
使用线程池主要为了解决以下问题:
重用线程池中的线程,来减少线程的创建和销毁, 一次创建多次使用。
对线程的维护和管理,比如定时开始,周期执行,并发数量控制
2.线程池参数
- corePoolSize: 核心线程数,默认情况下核心线程一直存活,即使处于闲置壮体啊也不会受到KeepAliveTime限制,除非将allowCoreThread设置为true
- maximumPoolSize:最大线程数,超过这个数量的线程会被阻塞,当任务队列没有设置大小的LinkedBlockingQueue时,这个值
- keepAliveTime:闲置线程存活时间(不包含核心线程),非核心线程的闲置超时时间,
- TimeUnit:时间单位
- workQueue:线程队列 常用队列 SynchronousQueue(同步队列),LinkedBlockingQueue,ArrayBlockingQueue
- threadFactory(): 线程工厂创建线程的方法
- new AbortPolicy() 队列已满,而且当前线程数量已经超过最大线程数量的异常处理
3.线程池中的threadpoolexector,每个参数是干嘛用的
4.线程池内部使用规则
线程池的线程执行规则跟任务队列有很大的关系:
下面都是假设任务队列没有大小限制:
1.如果线程数量<=线程核心数量,那么启动一个核心线程来执行任务,不会放入队列
2.如果线程数量>核心线程数,但<=最大线程数,并且任务队列是LinkedBlockingQueue的时候,超过核心线程数量的任务会放到队列中
3.如果线程数量>核心线程数,但<=最大线程数,并且任务队列是SynchononsQueue的时候,线程池会创建新的线程执行任务,也不会放到队列中,这些线程属于非核心线程,在任务完成后,闲置的时间达到了超过了时间就会被清除
4.如果线程数量>核心线程,并且>最大线程数量,并且任务队列是LinkedBlockingQueue的时候 将超过核心线程的任务放在队列中也就是LinkedBlockingQueue 没有大小闲置时,线程池的最大线程数设置是无效的,他的想成数量不回超过核心线程数
5.如果线程数量>核心线程,并且>最大线程数, 并且任务队列是SynchononsQueue的时候会应为线程拒绝添加而抛出异常
6.当LinkedBlockingQueue塞满时,新的任务会直接创建新的线程来执行,当创建的线程数量超过最大数量的时候会抛出异常
7.SyncchronousQueue没有数量限制,应为他根本不保留任务,直接交给线程池去执行,当任务超过最大线程数会直接抛出异常
5.有用过AtomicInteger吗?怎么用?
AtomicInteger 是 int 的原子操作,保证线程安全。
6.用过ThreadLocal吗?怎么用的? JDK1.2提供
7.程序、进程、线程的区别是什么?
程序:是一个指令的集合,程序不能独立执行,,只有被加载到内存中,系统为他分配资源之后才能执行
进程:一个执行的程序称为进程,进程好似系统分配资源的独立单位,每个进程都真有特定的地址空间,程序是进程的静态文本,进程是程序在系统内顺序执行的动态活动
线程:是进程的单一的连续控制流程,线程是cpu调度和分配的基本单位,是比进程更小的能独立运行的基本单位,也称为轻量级进程,线程不能独立存在,必须依附于某个进程,一个进程可以包含多个并行的线程,一个线程肯定属于一个进程,java虚拟机允许并发执行多个线程
8.Java中创建线程的方式
- 继承Thread类
- 实现Runnable接口
- 实现Callable、FutureTask包装器创建Thread线程
- 使用ExecutorService、callable、Future 实现又返回结果的线程
9.说说sleep 、yield 、join 、wait 区别:
sleep:方法需指定等待的时间,它可以让当前正在执行的线程在制定的时间内暂停执行,进入阻塞状态,该方法可以让其他优先级或者高优先级的线程得到执行的机会,也可以让低优先级的线程得到执行机会,但是sleep 不是释放“锁标志”也就说有synchronized同步块,其他线程仍让不能访问共享数据 ,用于线程
- Thread.sleep()方法用来暂停线程的执行, 将cpu放飞线程调度器
- Thread.sleep()方法是一个静态的方法,它暂停的是当前执行的线程
- Java有两种sleep方法,一个是毫秒的参数,一个是有毫秒和纳秒两个参数
- 与wait 不同sleep不回释放锁
- 如果其他线程终端了一个休眠的线程,sleep 会抛出异常 InterruptedException
- 休眠的线程在唤醒之后不保证能获取到cpu,他会先进入就绪状态,与其他线程竞争cpu
- 一个易错的地方,当调用sleep()方法后会暂停线程t,这事不对的,因为Thead.sleep()方法是一个静态方法,他会使当前线程 而不是t线程进入休眠状态
join:当前线程调用此方法的线程执行结束后在继续执行,join方法必须在线程start 之后调用才有意义
yield:它仅仅释放线程所占用的CPU资源,从而让其他线程有机会运行,但是并不能保证摸个特定的线程能够获取CPU资源,谁能获取cpu资源完全取决于调度器,在有些情况下调用yield方法的线程甚至会再次获取CPU资源,所以依赖yield的方法是不可靠的,它只能尽力而为,作用与线程
wait():
- wait只能同步(synchronized)环境中被调用,而sleep不需要
- 进入wait 状态的线程能够被 notify 和 notifyall 唤醒, 范式进入sleep 的线程是不能的
- wait通常有条件的去执行,线程会一直处于wait状态,直到某个条件变为真。但是sleep 仅仅让你线程进入睡眠状态
- wait方法在进入wait状态的时候会释放锁对象,但是sleep不会
wait 方法是针对一个被同步代码块加锁的对象