首先要介绍的是Object类的三个方法
wait(long timeout)
notify()
notifyAll()
这三个方法必须要在同步块中才能调用,即首先获取对象的monitor,常用的方式如下
synchronize(obj){
obj.wait()
...
}
当对象调用wait方法的时候,就意味着放弃了该资源(monitor),并进入了等待队列。
注:记得我们之前公司的产品,当一个线程需要睡眠的时候,就是用wait(long timeout)来实现的。我们的线程架构一般是
public void run(){
while(!shutdown){
...
do something
//需要sleep的时候
synchronize(obj){
obj.wait(time)
...
}
}
}
这样就可以通过shutdown这个变量来控制该线程的关闭,同时,如果系统在关闭的时候,该线程处于sleep状态,我们只需要调用notify()方法就可以将该线程从睡眠状态叫醒,然后关闭。如果这里用sleep()方法的话,就需要用interupt()方法。
protect boolean snooze(long sleeptime){
synchronized(obj){
if(wasAwoken){
wasAwoken=false;
return true;
}
try{
if(sleeptime > 0){
obj.wait(sleeptime);
if(wasAwoken){
wasAwoken=false;
return true;
}
return false;
}catch(InterruptedException ex){
log.info("Thread was interrupted-this should not happen,use wake() instead");
return true;
}
protect boolean wake(){
synchronized(obj){
wasAwoken=true;
obj.notify();
}
}
这样就可以实现线程的睡眠和唤醒了。
一般的大工程都会有很多deamon thread , 具体什么是deamon thread可以去查询,但是如果一个application 没有用户进程的话,JVM会自动关闭该application, 一般deamon thread 都是一个一直在run的线程。
1. 线程怎么样就关闭了??
如果一个线程的run方法执行完毕,则这个线程就关闭了,所以一般的deamon thread 的run方法都是一个循环。
像前面介绍的可以利用shutdown的变量来控制循环是否结束。从而使线程退出。
2. 线程的run方法和start方法
如果你直接调用一个线程的run方法,实际上还是在本线程执行了一个函数而已,并没有开启一个线程。只有当调用线程的start方法时候,才会在另一个线程中执行run方法。
3. 线程池的概念
ThreadPoolExecutor该类是线程池的主类,像常见的几种线程池都是通过工厂类来调用ThreadPoolExecutor() ,只是具体的参数不同。
参考以下的链接:https://blog.csdn.net/xiaojin21cen/article/details/87359148
public ThreadPoolExecutor(initcorePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler
initcorePoolSize:是指在空闲的时候,线程池中保留的线程池数
maximumPoolSize:是指线程池中最大的线程数
keepAliveTime:线池空闲的时间,当大于这个时间,空闲的线程会被销毁,达到initcorePoolSize的数值
TimeUnit:是指时间的单位
BlockingQueue:是指当线程达到initcorePoolSize的时候,进来的任务都需要提交到队列中,就是该队列。
另外两个参数具体不介绍了。
线程池的处理流程。
比如initcorePoolSize是10,maximumPoolSize是20,BlockingQueue是ArrayBlockingQueue(10-有界的队列)
1.当一个任务提交到线程池的时候,如果当前线程池中的线程小于initcorePoolSize -10,则立即会创建新的线程来执行该任务。
2.当一个任务提交到线程池的时候,当前线程池中的线程已经大于initcorePoolSize-10,则会将任务放到ArrayBlockingQueue中,等待空闲线程来执行。
3. 当一个任务提交到线程池的时候,当前线程池的线程已经大于initcorePoolSize-10,且ArrayBlockingQueue也满了,但是线程池中的线程数小于maximumPoolSize-20,则会创建线程来执行任务。
4.当一个任务提交到线程池的时候,线程数大于maximumPoolSize ,则会使用拒绝策略来处理。
不同的线程池,主要是initcorePoolSize,maximumPoolSize,以及BlockingQueue的差别,具体可以参考
https://www.jianshu.com/p/78424e42d4ea