Java线程池Executors的使用

1.Java通过Executors提供四种线程池:
● public static ExecutorService newCachedThreadPool()
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程,但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。
● public static ExecutorService newFixedThreadPool(int nThreads)
创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程,超出的线程会在队列中等待。
● public static ExecutorService newSingleThreadExecutor()
创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
● public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
创建一个定长线程池,支持定时及周期性任务执行。

前三个方法都可以配合接口ThreadFactory的实例一起使用。并且返回一个ExecutorService接口的实例

2.接口 ThreadFactory
根据需要创建新线程的对象。使用线程工厂就无需再手工编写对 new Thread 的调用了,从而允许应用程序使用特殊的线程子类、属性等等。
此接口最简单的实现就是:

public class SimpleThreadFactory implements ThreadFactory {
    public Thread newThread(Runnable r) {
        return new Thread(r);
    }
}

3.接口ExecutorService
该接口提供了管理终止的方法,以及可为跟踪一个或多个异步任务执行状况而生成 Future 的方法。
可以关闭 ExecutorService,这将导致其拒绝新任务。提供两个方法来关闭 ExecutorService。
shutdown()方法在终止前允许执行以前提交的任务,而 shutdownNow() 方法阻止等待任务的启动并试图停止当前正在执行的任务。在终止后,执行程序没有任务在执行,也没有任务在等待执行,并且无法提交新任务。应该关闭未使用的 ExecutorService以允许回收其资源。
通过创建并返回一个可用于取消执行和/或等待完成的 Future,方法submit扩展了基本方法
Executor.execute(java.lang.Runnable)。方法 invokeAny 和 invokeAll 是批量执行的最常用形式,它们执行任务 collection,然后等待至少一个或全部任务完成(可使用 ExecutorCompletionService类来编写这些方法的自定义变体)。
Executors类为创建ExecutorService提供了便捷的工厂方法。
注意1:它只有一个直接实现类ThreadPoolExecutor和间接实现类ScheduledThreadPoolExecutor。

4.创建标准线程池启动线程
提供一个简单的实现Runnable接口的线程
public class MyThread implements Runnable {
    public MyThread() {
    }
    public void run() {
        System.out.println(Thread.currentThread().getName() + "正在执行。。。");
    }
}
使用CachedThreadPool启动线程
public class CachedThreadPool {
    public static void main(String[] args) {
        ExecutorService exec = Executors.newCachedThreadPool();
        for (int i = 0; i < 5; i++)
            exec.execute(new MyThread());
        exec.shutdown();
    }
}
结果:


这种方式的特点是:可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们
使用FixedThreadPool启动线程

public class FixedThreadPool {
    public static void main(String[] args) {
        ExecutorService exec = Executors.newFixedThreadPool(2);
        for (int i = 0; i < 5; i++)
            exec.execute(new MyThread());
        exec.shutdown();
    }
}
结果:


从以上结果可以看出,newFixedThreadPool的参数指定了可以运行的线程的最大数目,超过这个数目的线程加进去以后,不会运行。其次,加入线程池的线程属于托管状态,线程的运行不受加入顺序的影响。
定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()

使用SingleThreadExecutor启动线程

public class SingleThreadExecutor {
    public static void main(String[] args) {
        ExecutorService exec = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 5; i++)
            exec.execute(new MyThread());
        exec.shutdown();
    }
}

结果依次输出,相当于顺序执行各个任务。

使用ScheduledThreadPool启动线程

public class ScheduledThreadPool {
    public static void main(String[] args) {
        // 创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
        ScheduledExecutorService exec = Executors.newScheduledThreadPool(2);
            MyThread t1 = new MyThread();
            exec.execute(t1);// 将线程放入池中进行执行
            MyThread t2 = new MyThread();
            exec.schedule(t2, 1000, TimeUnit.MILLISECONDS);// 使用延迟执行风格的方法
            exec.shutdown();
    }
}
结果:


5.配合ThreadFactory接口的使用
我们试图给线程加入daemon和priority的属性设置。
设置后台线程属性

public class DaemonThreadFactory implements ThreadFactory {
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r);
        t.setDaemon(true);
        return t;
    }
}
设置优先级属性
/**
 * 最高优先级
 */
public class MaxPriorityThreadFactory implements ThreadFactory {
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r);
        t.setPriority(Thread.MAX_PRIORITY);
        return t;
    }
}
/**
 * 最低优先级
 */
public class MinPriorityThreadFactory implements ThreadFactory {
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r);
        t.setPriority(Thread.MIN_PRIORITY);
        return t;
    }
}
启动带有属性设置的线程
public class ExecFromFactory {
    public static void main(String[] args) throws Exception {
        ExecutorService defaultExec = Executors.newCachedThreadPool();
        ExecutorService daemonExec = Executors
                .newCachedThreadPool(new DaemonThreadFactory());
        ExecutorService maxPriorityExec = Executors
                .newCachedThreadPool(new MaxPriorityThreadFactory());
        ExecutorService minPriorityExec = Executors
                .newCachedThreadPool(new MinPriorityThreadFactory());
        for (int i = 0; i < 10; i++)
            if (i == 3)
                daemonExec.execute(new MyThread());
            else if (i == 5)
                maxPriorityExec.execute(new MyThread());
            else if (i == 7)
                minPriorityExec.execute(new MyThread());
            else
                defaultExec.execute(new MyThread());
    }
}

就这么多了,小弟才疏学浅,如有不当之处,还请多多请教,大家共同学习,谢谢了


参考:

扫描二维码关注公众号,回复: 2510761 查看本文章


猜你喜欢

转载自blog.csdn.net/xuemengrui12/article/details/78543543