• java并发Executors学习笔记


    java并发(1)-Executors
    关于java创建多线程常用的两种方式,我就不多说了,无非就是实现Runnable和继承Thread。那么我们现在来说说其他的方法。

    Executors是什么
    Executors,我们称之为执行器,用于管理Thread对象,简化并发过程,其在客户端和任务执行之间提供了一个间接层。由中介执行任务。无需管理线程的生命周期。
    我们先是实现一个Runnable的类,其功能非常简单,就是在一个计数器,而且对于每一个创建的对象来说,其id都不一样,方便我们识别。

    class MyCountDownRunnale implements Runnable {
    private int countDown = 10;
    private static int taskCount = 0;
    private final int id = taskCount ++;
    public MyCountDownRunnale(){}
    public MyCountDownRunnale(int countDown) {
    this.countDown = countDown;
    }
    @Override
    public void run() {
    while (countDown -- > 0) {
    System.out.print(toString());
    Thread.yield();//线程都让出使用权,加入竞争。
    }
    }
    @Override
    public String toString() {
    return "$" + id + "<" + Thread.currentThread().getId() + ">(" + (countDown > 0 ? countDown : "Zero") + "), ";
    }
    }
    CachedThreadPool方式
    如下代码:

    ExecutorService exec = Executors.newCachedThreadPool();
    for (int i = 0; i < 5; i ++) {
    exec.execute(new MyCountDownRunnale());
    }
    exec.shutdown();//防止新线程提交
    执行结果:

    $1<12>(9), $3<14>(9), $1<12>(8), $2<13>(9), $0<11>(9),
    $2<13>(8), $1<12>(7), $3<14>(8), $4<15>(9), $3<14>(7),
    $1<12>(6), $2<13>(7), $0<11>(8), $2<13>(6), $1<12>(5),
    $3<14>(6), $4<15>(8), $3<14>(5), $1<12>(4), $2<13>(5),
    $3<14>(4), $2<13>(4), $0<11>(7), $2<13>(3), $3<14>(3),
    $1<12>(3), $4<15>(7), $1<12>(2), $3<14>(2), $2<13>(2),
    $0<11>(6), $2<13>(1), $3<14>(1), $2<13>(Zero), $1<12>(1),
    $4<15>(6), $1<12>(Zero), $3<14>(Zero), $0<11>(5), $4<15>(5),
    $0<11>(4), $4<15>(4), $0<11>(3), $4<15>(3), $0<11>(2),
    $4<15>(2), $0<11>(1), $4<15>(1), $0<11>(Zero), $4<15>(Zero),
    FixedThreadPool方式
    如下代码:

    ExecutorService exec =Executors.newFixedThreadPool(4);
    for (int i = 0; i < 5; i ++) {
    exec.execute(new MyCountDownRunnale());
    }
    exec.shutdown();//防止新线程提交
    执行结果:

    $0<11>(9), $3<14>(9), $2<13>(9), $1<12>(9), $2<13>(8),
    $3<14>(8), $0<11>(8), $3<14>(7), $0<11>(7), $2<13>(7),
    $1<12>(8), $2<13>(6), $0<11>(6), $3<14>(6), $0<11>(5),
    $2<13>(5), $1<12>(7), $2<13>(4), $0<11>(4), $3<14>(5),
    $0<11>(3), $2<13>(3), $1<12>(6), $2<13>(2), $3<14>(4),
    $2<13>(1), $0<11>(2), $1<12>(5), $0<11>(1), $2<13>(Zero),
    $3<14>(3), $0<11>(Zero), $1<12>(4), $1<12>(3), $3<14>(2),
    $1<12>(2), $4<13>(9), $1<12>(1), $1<12>(Zero), $3<14>(1),
    $4<13>(8), $3<14>(Zero), $4<13>(7), $4<13>(6), $4<13>(5),
    $4<13>(4), $4<13>(3), $4<13>(2), $4<13>(1), $4<13>(Zero),
    SingleThreadExecutor方式
    如下代码:

    ExecutorService exec = Executors.newSingleThreadExecutor();
    for (int i = 0; i < 5; i ++) {
    exec.execute(new MyCountDownRunnale());
    }
    exec.shutdown();//防止新线程提交
    执行结果:

    $0<11>(9), $0<11>(8), $0<11>(7), $0<11>(6), $0<11>(5),
    $0<11>(4), $0<11>(3), $0<11>(2), $0<11>(1), $0<11>(Zero),
    $1<11>(9), $1<11>(8), $1<11>(7), $1<11>(6), $1<11>(5),
    $1<11>(4), $1<11>(3), $1<11>(2), $1<11>(1), $1<11>(Zero),
    $2<11>(9), $2<11>(8), $2<11>(7), $2<11>(6), $2<11>(5),
    $2<11>(4), $2<11>(3), $2<11>(2), $2<11>(1), $2<11>(Zero),
    $3<11>(9), $3<11>(8), $3<11>(7), $3<11>(6), $3<11>(5),
    $3<11>(4), $3<11>(3), $3<11>(2), $3<11>(1), $3<11>(Zero),
    $4<11>(9), $4<11>(8), $4<11>(7), $4<11>(6), $4<11>(5),
    $4<11>(4), $4<11>(3), $4<11>(2), $4<11>(1), $4<11>(Zero),
    三者的区别
    看了三个不同的执行结果,我想大家都能知道1和2更3的区别了吧,
    1、第三种方式如其名,单线程跑的,他会把提交的任务,按照顺序执行,而且还是在同一个线程里执行的。
    2、那第一种和第二种的区别是什么呢?java培训技术构造方法的参数不一样,第二种方式中的参数代表的意思是,一次性预先执行代价昂贵的线程分配,之后就可直接使用了,不过不能滥用,因为数量有限。而第一种就是,执行过程中通常创建所需的数量的线程,然后回收旧线程的时候,停止创建线程。
    3、他们两个除了这个区别之外,还有一个重要的特性,就是FixedThreadPool保证了“没有两个线程”会被并发调用。
    4、如果一个线程实例请求加入FixedThreadPool时,如果该实例不存在,且没有达到线程池数目上线,则会创建一个实例,否则,会先加入等待序列,当FixedThreadPool中有一个线程停止并移出线程池后,线程实例才能加入线程池。
    5、CachedThreadPool中线程实例默认超时时间为60s,超过这个时间,线程实例停止并被移出CachedThreadPool,适用于生存期短、异步的线程任务。FixedThreadPool没有超时机制,适用于稳定且并发线程任务。关于这点,可以看源码中的代码Executors.java:
    如下,第三个参数就是超时的时间设置。0就是不超时。

    public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
    60L, TimeUnit.SECONDS,
    new SynchronousQueue<Runnable>());
    }
    public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
    0L, TimeUnit.MILLISECONDS,
    new LinkedBlockingQueue<Runnable>());
    }

  • 相关阅读:
    java基础——DecimalFormat
    剑指——重建二叉树
    error error: illegal character: 'u3000'
    Android: Unhandled exception java.net.malformedurlexception 异常笔记
    Android获取系统时间
    java基础——hashCode笔记
    golang 红黑树
    golang 实现跳表skiplist
    快排
    堆排序
  • 原文地址:https://www.cnblogs.com/gojava/p/4469411.html
Copyright © 2020-2023  润新知