线程池

线程池  


    1、创建一个空的任务容器

  2、在容器中初始化10个执行任务的线程,俗称消费者线程

  3、最开始这个容器是空的,所以线程都wait在上面

  4、直到一个外部线程往这个容器扔了一个“任务”,这时候就会唤醒消费者线程notify

  5、这个消费者线程从容器中取出”任务“,并且执行这个任务,任务完成,wait等待下一次任务到来

  6、如果短时间有很多任务在容器,就会唤醒所有线程notify,去执行这些任务

  在整个过程中,只需要在初始化池子的时候,会加载线程。之后都不会创建线程,而是循环使用已经存在的线程

 

自定义一个线程池


   ThreadPool

package com.thread.thread16;

import java.util.LinkedList;

public class ThreadPool {
    //线程池大小
    int threadPoolSize;

    //任务容器  这个是链表容器  Runnable是线程接口  创建线程需要实现这个接口
    LinkedList<Runnable> tasks = new LinkedList<Runnable>();

    //试图消费任务的线程
    public ThreadPool(){   //构造函数
        threadPoolSize = 10;  //线程池的大小

        //启动10个任务消费者线程
        synchronized (tasks) {//锁定这个任务
            for(int i=0; i<threadPoolSize; i++) {   //遍历线程池子的线程
                new TaskConsumeThread("任务消费者线程" + i).start();   //挨个启动线程   俗称初始化
            }
        }
    }

    public void add(Runnable r) {
        synchronized (tasks) {   //锁定这个任务容器
            tasks.add(r);   //将任务添加到容器中
            //唤醒等待的任务消费者线程
            tasks.notifyAll();   //将存放任务的容器内部线程全部唤醒
        }
    }

    class TaskConsumeThread extends Thread {   //内部线程类

        public TaskConsumeThread(String name) {   //构造函数   给线程取名字
            super(name);
        }

        Runnable task;  //单个线程
        public void run() {   //重写runnable接口中的run方法
            System.out.println("启动:" + this.getName());        //打印哪个线程被初始化
            while(true) {
                synchronized (tasks) {       //锁定任务容器
                    while(tasks.isEmpty()) {     //查看任务容器是否有任务  空就返回true 执行wait
                        try {
                            tasks.wait();   //没有任务  让线程们等一下下
                        }catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    //这个时候有任务  tasks不为空
                    task = tasks.removeLast();  //删除最后一个元素 并且返回元素  这个时候是派遣任务给线程
                    //允许添加任务的线程可以继续添加任务
                    tasks.notifyAll();
                }
                System.out.println(this.getName() + "获取到任务,并执行");   //看谁抢到这个任务
                task.run();   //线程争抢该任务
            }
        }
    }
}

  案例一:测试线程池抢占一个任务

package com.thread.thread16;

public 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("执行任务");
                    //执行任务的代码
                    //可以打印一段话
                    //访问一个文件
                    //可能做排序
                }
            };
            pool.add(task);  //将任务放入
            try {
                Thread.sleep(1000);
            }catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

  效果

   案例二:隔一定时间添加任务到容器中,保证每个线程都被利用到

package com.thread.thread16;

public class TestThread2 {
    public static void main(String[] args) {
        ThreadPool pool = new ThreadPool();   //创建线程池子
            int sleep = 1000;   //睡眠时间
            while(true) {
                pool.add(new Runnable() {  //池子里面去扔任务
                    @Override
                    public void run() {
                        System.out.println("执行任务");
                        try{
                            Thread.sleep(1000);  //每个任务 执行久一点   1秒钟   这样 就能看到其他线程也能一起抢占任务
                        }catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                });
            try {
                Thread.sleep(sleep);
                sleep = sleep > 100 ?sleep-100:sleep;  //如果执行时间大于100秒  则每次减100   直到减到100以下  直接返回sleep
            }catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

  效果

  案例三:java自带的线程池

package com.thread.thread16;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class TestThread3 {
    public static void main(String[] args)throws InterruptedException {
        //使用自带线程池子
        //10 代表线程池子中初始化了10个
        //15 代表如果10个线程不够了的话  就扩容到15
        //如果60秒  扩容的5个处于空闲  则回收线程  池子保持10个
        //linkedBlockingQueue 任务队列  放任务的地方
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(10, 15, 60, TimeUnit.SECONDS, new
                LinkedBlockingQueue<Runnable>());
        //线程执行
        threadPool.execute(new Runnable() {  //runnable是接口  这里实例化的是runnable接口的实现类
            @Override
            public void run() {    //重写run方法
                System.out.println("任务1");
            }
        });
    }
}

  效果

 

posted @ 2021-02-18 15:46  上天安排的最大嘛!  阅读(42)  评论(0编辑  收藏  举报