JAVA中线程小谈

首先要介绍的是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

猜你喜欢

转载自blog.csdn.net/sinat_33822516/article/details/90487645