码迷,mamicode.com
首页 > 编程语言 > 详细

Java线程池

时间:2018-09-22 17:00:16      阅读:147      评论:0      收藏:0      [点我收藏+]

标签:工厂方法   except   HERE   情况下   第一个   容器   executors   http   link   

系统启动一个新线程的成本是比较高的,因为它涉及与操作系统交互,在这种情况下,使用线程池可以很好地提高性能。
线程池的模式很像生产者消费者模式,消费的对象是一个一个的能够运行的任务。

线程池设计思路

1、准备一个任务容器。
2、一次性启动10个消费者线程。
3、刚开始任务容器是空的,所以线程都wait在上面。
4、直到一个外部线程往这个任务容器中扔了一个“任务”,就会有一个消费者线程被唤醒。
5、这个消费者线程取出“任务”,并且执行这个任务,执行完毕后,继续等待下一次任务的到来。
6、如果短时间内,有较多的任务加入,那么就会有多个线程被唤醒,去执行任务。

技术分享图片

自定义线程池

public class ThreadPool {

    int threadPoolSize;

    //任务队列
    LinkedList<Runnable> tasks=new LinkedList<>();

    public ThreadPool() {
        threadPoolSize=10;
        synchronized (tasks) {
            for (int i=0;i<threadPoolSize;i++) {
                new TaskConsumerThread("任务消费者线程"+i).start();
            }
        }
    }

    public void add(Runnable runnable) {
        synchronized (tasks) {
            tasks.add(runnable);
            tasks.notifyAll();
        }
    }

    class TaskConsumerThread extends Thread {

        public TaskConsumerThread(String name) {
            super(name);
        }

        public void run() {
            System.out.println("启动:" + this.getName());
            Runnable task;
            while (true) {
                synchronized (tasks) {
                    while (tasks.isEmpty()) {
                        try {
                            tasks.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    task=tasks.removeLast();
                    tasks.notifyAll();
                }
                System.out.println(this.getName() + "获取到任务,并执行");
                task.run();
            }
        }
    }
}

下面是一个测试

class TestThread{
    public static void main(String[] args) {
        ThreadPool pool=new ThreadPool();
        for (int i=0;i<5;i++) {
            Runnable task=new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName()+"正在执行任务");
                }
            };
            pool.add(task);
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

运行结果如下:

启动:任务消费者线程0
任务消费者线程0获取到任务,并执行
任务消费者线程0正在执行任务
启动:任务消费者线程1
启动:任务消费者线程2
启动:任务消费者线程3
启动:任务消费者线程4
启动:任务消费者线程5
启动:任务消费者线程6
启动:任务消费者线程7
启动:任务消费者线程8
启动:任务消费者线程9
任务消费者线程9获取到任务,并执行
任务消费者线程9正在执行任务
任务消费者线程9获取到任务,并执行
任务消费者线程9正在执行任务
任务消费者线程9获取到任务,并执行
任务消费者线程9正在执行任务
任务消费者线程9获取到任务,并执行
任务消费者线程9正在执行任务

Java内建线程池

在Java5之前,开发者必须手动实现自己的线程池;从Java5开始,Java内建支持线程池,新增一个Executors工厂类来产生线程池,该工厂类包含如下几个静态的工厂方法来创建线程池:

  • public static ExecutorService newCachedThreadPool():创建一个具有缓存功能的线程池,系统根据需要创建线程,这些线程将会被缓存在线程池中。
  • public static ExecutorService newFixedThreadPool(int nThreads):创建一个可重用的、具有固定线程数的线程池。
  • public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize):创建具有指定线程数的线程池,它可以指定延迟后执行线程任务。

ExecutorService代表尽快执行线程的线程池,程序只要将一个Runnable对象或Callable对象提交给该线程池(submit方法),该线程池就会尽快执行该任务。
用完一个线程池后,应该调用该线程池的shutdown()方法,该方法将启动线程池的关闭序列,调用shutdown()方法后的线程池不再接收新任务。

shutdown():不会立即终止线程池,而是要等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务。
shutdownNow():立即终止线程池,并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务。

ExecutorService executorService= Executors.newFixedThreadPool(3);

executorService.submit(new Runnable() {
    @Override
    public void run() {
        System.out.println("第一个线程池执行第一个线程任务");
    }
});

executorService.shutdown();

ScheduledExecutorService scheduledExecutorService=Executors.newScheduledThreadPool(3);
scheduledExecutorService.schedule(new Runnable() {
    @Override
    public void run() {
        System.out.println("第二个线程池执行第一个线程任务");
    }
},10, TimeUnit.SECONDS);

scheduledExecutorService.shutdown();

使用线程池优点总结:
1、系统启动一个新线程的成本是比较高的,因为它涉及与操作系统交互,在这种情况下,使用线程池可以很好地提高性能,尤其是当程序中需要创建大量生存期很短的线程时,应该使用线程池。
2、使用线程池可以有效地控制系统中并发线程的数量,当系统中包含大量并发线程时,会导致系统性能剧烈下降,甚至导致JVM崩溃,而线程池的最大线程数参数可以控制系统中并发线程数量。
3、能够对线程进行简单的管理,并提供定时执行、间隔执行等功能。

参考:HowtoJ

Java线程池

标签:工厂方法   except   HERE   情况下   第一个   容器   executors   http   link   

原文地址:https://www.cnblogs.com/sqmax/p/9690311.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!