线程池入门

一.线程池的概念与引入

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()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值