多线程学习总结

1.    

    创建线程的两种方式 new 一个 继承了Thread的类或者实现Runnable接口的类的对象作为参数传给Thread类的构造方法。

    isAlive() 的功能是判断当前的线程是否处于活动状态。(活动状态就是线程已经启动且尚未终止,线程处于正在运行或者准备开始运行的状态,就认为线程是
    存活的)
    
     sleep(long) long是毫秒数,指让this.currentThread()休眠long毫秒,不释放锁。

    getId()作用是取得线程的唯一标识

1.停止线程的方式:

    方式一:interrupt()

    实际上没有正真的停止,而是将线程标记为停止,然后通过抛出异常的方式结束线程

    包括(先sleep()然后interrupt() 或者先interrupt()然后sleep() 均会抛出 

java.lang.InterruptedException:sleep interrupted

    this.interrupted():测试当前线程是否已经中断(指的是运行interrupted方法的那个线程,并且该方法有清除中断状态的作用)。

    this.isInterrupted():测试线程是否已经中断。

        以上两个方法是判断线程有没有调用interrupt()方法。
    

    方式二:stop() 
        
        该方式是非常暴力的。在JDK中被标明是“作废/过期”,不建议使用

    方式三:interrupt()与return结合,不如方式一,return 太多污染代码严重

2.暂停线程

    suspend()线程暂停 resume()线程恢复

    Thread.yield()是放弃当前的CPU资源,将它让给其他的任务去占用CPU执行时间。但放弃的时间不确定,有可能刚刚放弃,又马上获得。    

3.线程优先级

    setPriority();getPriority(); 线程优先级具有继承性,这个继承指的是(比如A线程启动B线

程,那么B线程继承A线程的优先级)

4.守护线程  

 
  典型的守护线程垃圾回收线程 将一个线程设置为守护线程是用线程的setDaemon(true)方法


二 

1.同步锁synchronized 是对象锁,亦synchronized锁的是对象,是排队运行的。只有共享资源的读

  写访问才需要同步化(多个线程访问同一个实例/对象)
    
  线程A先持有object对象锁,不影响线程B异步调用object非synchronized类型的方法,如果调用的是

  object对象中synchronized类型的方法,需等待lock锁释放,也就是同步。
    

2 脏读: 读取实例变量时,数据出现交叉,此值已经被其他线程更改过了。

3 synchronized 锁重入 当一个线程得到一个对象锁后,再次请求此对象锁是还可以得到该锁。

    可重入锁也支持在父子类继承的环境中,子类可以通过“可重入锁”调用父类的同步方法。
    
4 出现异常,锁自动释放

5 同步不具有继承性,解决方案:在子类中添加synchronized

6 synchronized方法是对当前对象加锁,而synchronized代码块是对某一个对象进行加锁。

7 synchronized 使用的是“对象监视器”是一个,synchronized(this)代码块也是锁定当前对象的。

  多个线程调用同一个对象中的不同名称的synchronized同步方法或synchronized(this)同步代码块时

,调用的效果就是顺序执行,也就是同步的,阻塞的。

8 synchronized 同步方法对象锁实际上就是this。非this对象锁,锁定同步代码块,就是与同步方法异

步,不与其他同步方法争锁,可大大提高效率。

9 synchronized  当多个线程执行 x 对象的synchronized 方法,x对象方法里的synchronized(this)以

及synchronized(x)均同步

10 类锁 synchronized 加到static 方法上,类锁对所有对象实例起作用,也就是说,只要是该类的对象,

多个对象之间调用该类的任意 synchronized static 方法时同步。synchronized(class) 代码块的作用与

synchronized static 方法的作用一样。并且synchronized static 与 synchronized(class) 都是用的同

一把锁,就是该类的类对象(比如 A.java 类 那么该锁就是A.class)

11 String 常量池的特性

    String a= "a";实际上是从常量池中取得的a 对象,好比是枚举,String a = new String("a");

是新建的a 对象,不是常量池中的那个a 对象。对于对象测试结果是 Object obj1 = new Object();

Object obj2 = new Object(); 

12 内置类
    
    其他类(非子类)想要调用非静态内部类的构造方法首先要创建外部类对象,比如A类里面包含B类 A

 那么main 方法调用B类构造方法 B b =new A().new B(); 调用静态内部类构造方法可以直接调用

B b = new B();

13 锁对象的改变,对象锁有可能被其他线程改变,当一个线程运行到synchronized时候这个锁对象是什么,

就争夺什么,即使在等待的过程中锁对象发生了改变,这个线程等待的那把锁还是之前的对象。

对于同一个对象,即使对象属性被改变,运行结果还是同步,因为锁对象没有改变。


14 volatile 解决私有堆栈中的值和公共堆栈中的值不同步。强制性从公共堆栈中进行取值。
 
使用volatile 关键字增加了实例变量在多个线程之间的可见性。最致命的缺点就是不支持原子性

线程安全包含原子性和可见性两个方面,Java的同步机制都是围绕这两个方面来确保线程安全的。
 
  

15 JAVA 多线程--线程安全之原子性,有序性和可见性

原子性 : 操作是不可分的,比如a++;是 读取a 的值,a的值加1,然后赋给a,或者说同步性

可见性 : 关键字volatile 可以理解成直接操作主内存,这就涉及到java的happens-before关系了

有序性 :有序性是指程序在执行的时候,程序的代码执行顺序和语句的顺序是一致的。

在Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序过程不会影响到单线程程序的执行,

却会影响到多线程并发执行的正确性。

16 原子类import java.util.concurrent.atomic.AtomicInteger; 不用同步就能保证线程安全,原子类

也并不完全安全

synchronized 代码块有volatile同步功能 关键字 synchronized可以使多个线程访问同一个资源具有同步性,

而且它还具有将线程工作内存中的私有变量与公共内存中的变量同步的功能。包含两个特性:互斥性和可见性

同步synchronized不仅可以解决一个线程看到对象处于不一致状态,还可以保证进入同步方法或者代码块的每个

线程,都看到由同一个锁保护之前所有的修改效果。

三 线程间通信(大大提高CPU利用率)

    1  wait(),notify() 均在同步方法或者同步代码块中使用,(使用是锁对象.方法)。如果线程没有持有该对象的对象级别锁,会抛出

IllegalMonitorStateException,它是RuntimeException的一个子类,因此不需要try-catch捕获。在调用wait()

方法后,当前线程释放锁,代码停止执行,直到被唤醒。在执行notify() 方法后,当前线程不是马上释放该对象锁,

呈wait() 状态的线程也并不能马上获取对象锁,要等到执行notify()方法的线程将程序执行完,也就是退出

synchronized代码块后,当前线程才会释放锁。当第一个获得该对象锁的wait线程运行完毕后,它会释放掉该对象锁,

此时如果该对象没再次使用notify语句,其它等待的线程也不会获得锁,直到该对象发出notify或者notifyAll。

如果发出notify操作时没有处于阻塞状态中线程,那么该命令会被忽略。

wait()方法可以使调用该方法的线程释放共享资源的锁,然后从运行状态退出,进入等待队列,直到被再次唤醒。

notify()方法唤醒其中等待同一共享资源的“一个”线程。
    
notifyAll()方法唤醒等待队列中等待同一共享资源的所有线程。优先级最高的那个线程最先执行,但也有可能

随机执行。
    
2  线程进入Runnable状态大体分为如下5种情况(可运行状态)

调用sleep() 方法后经过的时间超过了指定的休眠时间

线程调用的阻塞IO已经返回,阻塞方法执行完毕。

线程成功获得了试图同步的监视器

线程正在等待某个通知,其他线程发出了通知

处于挂起状态的线程调用了 resume恢复方法。

3  Blocked阻塞状态

线程调用sleep方法。

线程调用了阻塞式IO方法,在该方法返回前,该线程被阻塞

同步监视器正在被其他线程所持有

线程等待某个通知

程序调用了suspend方法将该线程挂起。此方法容易导致死锁,尽量避免使用该方法。

run()方法运行结束后进入销毁阶段,整个线程执行完毕。
    
每个锁对象都有两个队列,一个是就绪队列,一个是阻塞队列。
    
3  当方法wait()被执行后,锁被自动释放,但是执行完notify()方法,锁却不自动释放,当程序执行完同步代码

块释放所在资源(sleep()线程进入阻塞,但是不释放锁对象)

4  当线程呈wait()状态时,调用线程对象的interrupt()方法会出现InterruptedException

5  执行完同步代码块就会释放对象锁 

 在执行同步代码块的过程中,遇到异常而导致线程终止,锁也会被释放

在执行同步代码块的过程中,执行了锁所属对象的 wait()方法,这个线程会释放对象锁,而此线程对象会进入线程等待

池中。

6  使用notify()一次只随机通知一个线程进行唤醒。

7 wait(long) 等待某一时间内是否有线程对锁进行唤醒,如果没有,long毫秒后自动唤醒。当然也可以在long毫秒之内被

其他线程唤醒。

8 通知过早,则会打乱程序正常的运行逻辑。在使用wait/notify 模式时,还要注意另外一种情况,也就是wait等待条件发

生了变化,也容易造成程序逻辑的混乱。

9 生产者,消费者模式,就是一个线程生产一个线程等待,有产品生产线程等待消费线程消费完通知生产线程生产,

没有产品消费等待生产线程生产完通知消费线程消费。(一生产一消费)

多生产-多消费使用notify 造成假死,原因是连续唤醒同类。解决方法就是唤醒所有等待线程。if语句 改while;


java.lang.ThreadGroup.enumerate(Thread[] list) 方法复制该线程组及其子组中的所有活动线程到指定的数组。
java.lang.Thread.activeCount() 活动线程的当前线程的线程组中的数量


线程状态 调用wait()  Thread.getState() WAITING  正常的RUNNABLE

10 操作栈:一生产一消费(if-notify);一生产多消费,多生产一消费,多生产多消费(while-notifyAll)


11,管道流(pipeStream)是一种特殊的流,用于在不同线程间直接传递数据。在JDK中提供了4个类来使线程间可以通信

 PipedInputStream 和 PipedOutputStream; PipedReader 和 PipedWriter、

对输入流只能进行读操作,对输出流只能进行写操作,程序中需要根据待传输数据的不同特性而使用不同的流

13 join()遇到interrupt()方法,则会出现InterruptedException异常

14 join(long)设定的毫秒数,如果调用join的那个线程对象执行完,join所在线程立刻被唤醒,不会等待long时间在唤醒;

(自己理解:就是说在调用join的那个方法执行完会唤醒此线程,同时开了一个定时器线程,long毫秒后也会唤醒此线程)

15 join(long) 与 sleep(long) 的区别

方法join(long)具有释放锁的特点,方法sleep(long) 不释放锁。wait(0)与wait()方法的实际意义是一样的,都表示在没有

唤醒的情况下该线程一直处于等待状态。

16. 当线程遇到join()方法所有与join方法共同争抢锁的线程都要执行完,该线程才能再次获得锁执行下边的代码。

17.类ThreadLocal解决每个线程绑定自己的值。可以将ThreadLocal类比喻成全局存放数据的盒子。盒子中可以存储每个线程的私有数据

  set(),get()方法使用 多个线程向ThreadLocal对象里面set值,但是他们各自取得值还是各自的,相互不影响,好像是隔离的。

  ThreadLocal 对象没有set()时,get()==null; 也可以继承ThreadLocal类重写initialValue()方法,给对象赋默认值。主线程与子线程
    
  获取的值不一定相同,比如返回 new Date() 这个值调用get()方法产生的,不同的线程不同(自己理解:因为对象不同)

  类InheritableThreadLocal 可以让子线程继承父线程的值。(就是被启动的线程的 该类及其子类的对象的get()方法获得的值继承启动

  该线程所属的线程的值)继承的同时还可以对值进一步处理。

    public class InheritableThread extends InheritableThreadLocal{
        
        @Override
        protected Object initialValue(){

            return new Date().getTime();
        }
        
        protectedObject childValue(Object parentValue){
            
            return parentValue+"我在子线程加的~!";
        }
        
    }

  值得注意的:在使用InheritableThreadLocal类需要注意,如果子线程在取值的同时,主线程将InheritableThreadLocal中的值进行更改

 那么子线程取到的值还是旧值。
    
四  LOCK 的使用

    1.  ReentrantLock 类的使用

    ReentrantReadWriteLock 类                                            

    Condition 类的使用比wait()和notify()/notifyAll() 更灵活。使用notify()/notifyAll()方法进行通知时,被通知的线程却是由JVM
    
    随机选择的。Condition可以实现前面介绍的"选择性通知"。而synchronized相当于整个Lock对象只有一个单一的Condition对象,所有的
    
    线程都注册在它一个对象的身上。线程开始notifyAll()时,需要通知所有WAITING线程,    没有选择权,会出现相当大的效率问题。

    使用ReentrantLock对象可以唤醒指定种类的线程,这是控制部分线程行为的方便方式。

    公平锁与非公平锁,公平锁表示线程获取锁的顺序时按照线程加锁的顺序来分配的,即先来先得的FIFO先进先出顺序。

    公平锁创建 ReentrantLock lock = new ReentrantLock(true);非公平锁  ReentrantLock lock = new ReentrantLock(false);

    公平锁也只能保证基本有序,

 2. 方法 getHoldCount()、getQueueLength()和getWaitQueueLength()的测试  

     lock.getHoldCount() 锁定的线程个数,也就是调用lock()方法的次数。

     getQueueLength()  等待获取锁的线程的个数

     getWaitQueueLength(Condition condition) 作用返回等待此锁定相关的给定条件Condition的线程估计数。比如5个线程,每个线程

     都执行了同一个condition对象的await()方法,则调用getWaitQueueLength(Condition condition)方法返回的int值是5.

 3  方法 hasQueuedThread()、hasQueuedThreads()和hasWaiters()

      boolean hasQueuedThread(Thread thread)的作用时查询指定的线程是否在等待获取此锁定
    
      boolean hasQueuedThreads()的作用时查询是否有线程正在等待获取此锁定

      boolean hasWaiters(Condition condition) 的作用是查询是否有线程正在等待与此锁有关的condition条件。

      boolean isFair() 的作用是判断是不是公平锁

      boolean isHeldByCurrentThread()的作用是查询当前线程是否保持此锁定。
 
      boolean isLocked()的作用是查询此锁定是否由任意线程保持。
    
      void lockInterruptibly()作用是:如果当前线程未被中断,则获取锁定,如果已经被中断则出现异常。 

      boolean tryLock()的作用是,仅在调用时锁定未被另一个线程保持的情况下,才获取该锁定。

      boolean tryLock(long timeout, TimeUnit unit) 的作用是,如果锁定在给定等待时间内没有被另一个线程保持,

      且当前线程未被中断,则获取该锁定。TimeUnit时间单位。

      awaitUninterruptibly()与 await()相似,但是前者在遇到interrupt()方法时不抛异常,而后者抛出InterruptedException

      awaitUntil(Date) 等待多少时间后自动唤醒,当然也可以被其他线程唤醒。
    
  4   类ReentrantReadWriteLock 读写锁,一个是读操作相关的锁,也称共享锁;另一个是写操作相关的锁,也称排它锁。在没有线程Thread

      进行写操作时,进行读取操作的多个Thread都可以获取读锁,而进行写入操作的Thread只有在获取写锁后才能进行写入操作。即多个

      Thread 可以同时进行读取操作,但是同一时刻只允许一个Thread进行写入操作。 该类对象的两个方法 lock.readLock().lock()与
    
      lock.writeLock().lock(); "读写"、"写读"、"写写"都是互斥的;而“读读”是异步的,非互斥。即只要出现写操作就是互斥的。

五  定时器

    Timer 类的主要作用就是设置计划任务,封装任务的类却是TimerTask是一个抽象类。Timer是个抽象类

    Timer的schedule(TimerTask task,Date time) 该方法的作用是在指定的日期执行一次某一个任务。

 1. 执行任务的时间晚于当前时间--在未来执行的效果。Calendar的add(),比如ca.add(Calendar.SECOND, 10)就是当前时间加10后的那个时间。

    new Timer()会一直运行 new Timer(true)时守护线程,TimerTask任务来不及执行。
    
    如果执行任务的时间早于当前时间,则立即执行task任务。
    
    Timer 中允许有多个TimerTask任务及延时。

2.  对于同一个Timer对象TimerTask是以队列的方式一个一个被顺序执行,所以执行的时间有可能和预期的时候不一致,因为前面的任务有可能消耗的时间较长,后面

    的任务运行的时间也被延后。

3.  方法schedule(TimerTask task,Date firstTime, long period) 作用是在指定的间隔周期,无限循环地执行某一个任务。

4.   TimerTask类中的cancel()方法的作用是将自身从任务队列中进行清除。

5.   TimerTask类的cancel()方法的作用是将自身从任务队列中进行清除。 Timer类的cancel()方法是将任务队列中的方法全部清除。Timer的cancel()方法有时并

     一定会停止计划任务,而是正常执行。 原因是Timer类中的cancel()方法有时并没有争抢到queue锁,则让TimerTask类中的任务正常执行。

6.  schedule(TimerTask task,long delay)  在当前时间之后 delay 毫秒数后执行一次TimerTask任务。

    schedule(TimerTask task,long delay, long period)方法当前的时间为参考时间,在此时间基础上延迟指定毫秒数,再以某一间隔时间无限次数地执行某一个

    任务。凡是使用方法中带有period参数的,都是无限循环执行TimerTask中地任务。

7. 方法scheduleAtFixedRate(TimerTask task, Date firstTime,long period); schedule 和 scheduleAtFixedRate都是顺序执行,所以不要考虑非线程安全的情况

   主要区别只在于有没有追赶特性。就是两个时间段内的时间所对应的Task任务被"补充性"的执行。就是如果计划执行时间早于当前时间,那么该方法快速执行多次任

   务补充这段时间空缺。

六  单例模式与多线程

     1.使用DCL 双检查锁机制解决多线程的延迟加载单例设计模式。或者使用静态内部类解决此问题,但是静态内置类可以达到线程安全问题,但如果遇到序列化对象时

    ,使用默认的方式运行得到的结果还是多例的。

     序列化对象解决办法就是在反序列化中使用readResolve()方法。

    public class MyObject implements Serializable{
    
        private static final long serialVersionUID = 888L;
    
        private static class MyObjectHandler{
        private static final MyObject myObject = new MyObject();
        };
    
        private MyObject(){
        
        }
    
        public static MyObject getInstance(){
        return MyObjectHandler.myObject;
        }
    
        protected  Object readResolve() throws ObjectStreamException{

        System.out.println("调用了readResolve方法!");
        return MyObjectHandler.myObject;
        }
    
    }

        使用时 MyObject mo = MyObject.getInstance()是单例的。

    序列化 一个对象其实就是,把一个对象通过存成文件,然后在从文件中读出对象。

    2.静态代码块中的代码在实用类的时候就已经执行了,所以可以利用静态代码块的这个特性来实现单例模式

    
    七 

    1.  线程对象在不同的运行时期有不同的状态,状态信息就存在于State枚举类中,

    NEW:至今尚未启动的线程处于这种状态。

        RUNNABLE:正在Java虚拟机中执行的线程处于这种状态。

    BLOCKED: 受阻塞并等待某个监视器锁的线程处于这种状态

    WAITING: 无限期地等待另一个线程来执行某一特定操作的线程处于这种状态

    TIMED WAITING: 等待另一个线程来执行取决于指定等待时间的操作的线程处于这种状态。

    TERMINATED: 已退出的线程处于这种状态。

   2.  线程组:可以把线程归属到某一个线程组中,线程组中可以有线程对象,也可以有线程组,组中还可以有线程

       线程组的作用是,可以批量的管理线程或线程组对象,有效地对线程或线程组对象进行组织。

    
       线程对象关联线程组:1级关联就是父对象有子对象,但并不创建子孙对象。

       线程组自动归到当前线程组中。在实例化一个ThreadGroup线程组x时如果不指定所属的线程组,则x线程组自动归到当前线程对象所属的线程组中。

       JVM的根线程组是system,再取父线程组则出现空异常。
 
   3.  通过将线程归属到线程组中,当调用线程组的interrupt()方法时,可以将该组中的所有正在运行的线程批量停止。
    
   4.  递归与非递归取得组内对象

    ThreadGroup[] threadGroup = new ThreadGroup[Thread.currentThread().getThreadGroup().activeCount()];
        Thread.currentThread().getThreadGroup().enumerate(threadGroup,true/false); //传true 递归,传false 非递归

    所谓递归就是可以遍历组中组,非递归只能遍历本组下的组                                                                                                                   
   5. 使线程具有有序性,原理就是wait() 与notifyAll()结合使用,类似生产与消费者模式。
 
   SimpleDateFormat 非线程安全,使用单例的SimpleDateFormat类在多线程的环境中处理日期,极易出现日期转换错误的情况。解决办法使用多个

   SimpleDateFormat类的实例。ThreadLocal类能使线程绑定到指定对象,使用该类也可以解决多线程环境下SimpleDateFormat类处理错误的情况。

   6. UncaughtExceptionHandler类,可以对发生的异常进行有效的处理。线程对象的setUncaughtExceptionHandler()作用是对指定的线程对象设置默认的

     异常处理器。setDefaultUncaughtExceptionHandler()的作用是为指定线程类的所有线程对象设置默认的异常处理器。
    

拓展:创建线程的第三种方式是,跟实现Runnable接口差不多,new Thread(new FutureTask<T>(new Callable<T>(){ 重写call() }))

    实现Callable接口重写Call()方法,创建一个对象传给FutureTask的一个对象,让后把该对象做参数传给Thread();

    采用实现Runnable、Callable接口的方式创建多线程时,优势是:线程类只是实现了Runnable接口或Callable接口,还可以继承其他类。

    在这种方式下,多个线程可以共享同一个target对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU、代码和数据分开,形成清晰的模

        型,较好地体现了面向对象的思想。
    
    劣势是:

    编程稍微复杂,如果要访问当前线程,则必须使用Thread.currentThread()方法。

    采用继承Thread类方式:

    (1)优点:编写简单,如果需要访问当前线程,无需使用Thread.currentThread()方法,直接使用this,即可获得当前线程。

    (2)缺点:因为线程类已经继承了Thread类,所以不能再继承其他的父类。

    采用实现Runnable接口方式:

    (1)优点:线程类只是实现了Runable接口,还可以继承其他的类。在这种方式下,可以多个线程共享同一个目标对象,所以非常适合多个相同线程来处理同一

            份资源的情况,从而可以将CPU代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。

    (2)缺点:编程稍微复杂,如果需要访问当前线程,必须使用Thread.currentThread()方法。

    线程池创建线程 例: ExecutorService es= Executors.newCachedThreadPool();  es.execute(Runnable对象)

    https://blog.csdn.net/m0_37840000/article/details/79756932(线程池详解)

     自定义线程池,可以用ThreadPoolExecutor类创建,它有多个构造方法来创建线程池,用该类很容易实现自定义的线程池,这里先贴上示例程序:
    
] view plai

复制代码
import java.util.concurrent.ArrayBlockingQueue;   
import java.util.concurrent.BlockingQueue;   
import java.util.concurrent.ThreadPoolExecutor;   
import java.util.concurrent.TimeUnit;   
  
public class ThreadPoolTest{   
    public static void main(String[] args){   
        //创建等待队列   
        BlockingQueue<Runnable> bqueue = new ArrayBlockingQueue<Runnable>(20);   
        //创建线程池,池中保存的线程数为3,允许的最大线程数为5  
        ThreadPoolExecutor pool = new ThreadPoolExecutor(3,5,50,TimeUnit.MILLISECONDS,bqueue);   
        //创建七个任务   
        Runnable t1 = new MyThread();   
        Runnable t2 = new MyThread();   
        Runnable t3 = new MyThread();   
        Runnable t4 = new MyThread();   
        Runnable t5 = new MyThread();   
        Runnable t6 = new MyThread();   
        Runnable t7 = new MyThread();   
        //每个任务会在一个线程上执行  
        pool.execute(t1);   
        pool.execute(t2);   
        pool.execute(t3);   
        pool.execute(t4);   
        pool.execute(t5);   
        pool.execute(t6);   
        pool.execute(t7);   
        //关闭线程池   
        pool.shutdown();   
    }   
}   
  
class MyThread implements Runnable{   
    @Override   
    public void run(){   
        System.out.println(Thread.currentThread().getName() + "正在执行。。。");   
        try{   
            Thread.sleep(100);   
        }catch(InterruptedException e){   
            e.printStackTrace();   
        }   
    }   
}  

public ThreadPoolExecutor (int corePoolSize, int maximumPoolSize, long         keepAliveTime, TimeUnit unit,BlockingQueue<Runnable> workQueue)
 

corePoolSize:线程池中所保存的线程数,包括空闲线程。

maximumPoolSize:池中允许的最大线程数。

keepAliveTime:当线程数大于核心数时,该参数为所有的任务终止前,多余的空闲线程等待新任务的最长时间。

unit:等待时间的单位。

workQueue:任务执行前保存任务的队列,仅保存由execute方法提交的Runnable任务。
    
    
          


      

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章