线程池的基本用法与相对定时+绝对定时的策略

来源:互联网 发布:java post上传图片 编辑:程序博客网 时间:2024/05/31 18:31

一.线程池的概念与引入

1.线程池的引入

首先介绍在tcp服务器变成模型的原理,每一个客户端连接用一个单独的线程为之服务,当与客户端的会话结束时,线程也就结束了,即每来一个客户端连接,服务器端就要创建一个新线程。这好比假设每个报名学员都要通过我来亲自接待,以便给每个学员一种好的感觉,但每个学员报名手续要花费半小时,对于50名同学,我一个个接待何为之办理手续,显然不实际,我会怎么做呢?我会闲接待每一个学员,打完招呼后,再把他分配给一名工作人员去办理手续,这样,我就接待了每名学员

如果访问服务器的客户端很多,那么服务器要不断地创建和销毁线程,这将严重影响服务器的性能.如果真的来一名学员,我们都安排一名新工作人员为之服务,也是不可能的,那公司岂不是要招聘很多工作人员?而是应该一名工作人员服务完一名学员,空闲下来后,一旦有新的学员要服务,我又立即安排该工作人员为新学员服务。线程池的概念与此类似,首先创建一些线程,它们的集合称为线程池,当服务器接受到一个客户请求后,就从线程池中取出一个空闲的线程为之服务,服务完后不关闭该线程,而是将该线程还回到线程池中

在线程池的变成模式下,任务是提交给整个线程池,而不是直接交给某个线程,线程池在拿到任务后,它就在内部找有无空闲的线程,再把任务交给内部某个空闲的线程,这就是封装。记住,任务是提交给整个线程池,一个线程同时只能执行一个任务,但可以同时向一个线程池提交多个任务

  • 线程池的概念与Executors类的应用

  • 做服务器的话,就会用到线程池这个知识

2.创建固定大小的线程池

public class ThreadPoolTest {    public static void main(String[] args) {        ExecutorService threadPool = Executors.newFixedThreadPool(3);//固定的线程池        for(int i = 1 ;i<=10;i++) {            final int task = i;            threadPool.execute(new Runnable() {                @Override                public void run() {                    for (int j = 1; j < 10; j++) {                        try {                            Thread.sleep(20);                        } catch (InterruptedException e) {                            e.printStackTrace();                        }                        System.out.println(Thread.currentThread().getName() + " is looping of " + j + " for task of " + task);                    }                }            });        }        System.out.println("all of 10 tasks have committed! ");    }}

这里写图片描述

  • 因为只有3个线程,所以一直只有3个线程运作

3.创建缓存线程池

public class ThreadPoolTest {    public static void main(String[] args) {        ExecutorService threadPool = Executors.newCachedThreadPool();//缓存的线程池  当任务来了,服务不过来了,自动增加线程,它里面对应线程是不定的 线程数量是动态变化的        for(int i = 1 ;i<=10;i++) {            final int task = i;            threadPool.execute(new Runnable() {                @Override                public void run() {                    for (int j = 1; j < 10; j++) {                        try {                            Thread.sleep(20);                        } catch (InterruptedException e) {                            e.printStackTrace();                        }                        System.out.println(Thread.currentThread().getName() + " is looping of " + j + " for task of " + task);                    }                }            });        }        System.out.println("all of 10 tasks have committed! ");    }}

这里写图片描述

4.创建单一线程池(如果实现线程死掉后重新启动)

public class ThreadPoolTest {    public static void main(String[] args) {        ExecutorService threadPool = Executors.newSingleThreadExecutor();//单线程 如果池子里的线程死了,它会立马产生一个新的线程,反正就是一直保持一个线程的存在        for(int i = 1 ;i<=10;i++) {            final int task = i;            threadPool.execute(new Runnable() {                @Override                public void run() {                    for (int j = 1; j < 10; j++) {                        try {                            Thread.sleep(20);                        } catch (InterruptedException e) {                            e.printStackTrace();                        }                        System.out.println(Thread.currentThread().getName() + " is looping of " + j + " for task of " + task);                    }                }            });        }        System.out.println("all of 10 tasks have committed! ");    }}

这里写图片描述

二.关闭线程池

  • shutdown与shutdownNow的比较
    • shutdown();//池子里面没有任何任务了,就关闭了
    • shutdownNow();立即关闭

三.用线程池启动定时器

1.隔几秒炸

Executors.newScheduledThreadPool(3).schedule(new Runnable() {            @Override            public void run() {                System.out.println("bombing");            }        },        10,                TimeUnit.SECONDS);

2.隔几秒炸,之后几秒循环炸

Executors.newScheduledThreadPool(3).scheduleAtFixedRate(new Runnable() {//固定频率                                                         @Override                                                         public void run() {                                                             System.out.println("bombing");                                                         }                                                     },                6,                2,                TimeUnit.SECONDS);
  • 调用ScheduledExecutorService的schedule方法,返回ScheduleFuture对象可以取消任务

  • 支持间隔重复任务的定时方式,不直接支持绝对定时方式,需要转换成相对时间方式

  • 比如如果你想定在今晚凌晨3点,但是没有这种方法,直接指定Date方法

    • 凌晨三点的时间-此刻的时间
Date.getTime()-System.currentTimeMillis()

转载地址

阅读全文
0 0