一步步实现WebServer中间件——自己实现一个线程池

来源:互联网 发布:淘宝代购怎么辨别真假 编辑:程序博客网 时间:2024/06/07 21:21

线程的一些基本概念:在操作系统中,进程是一个程序运行时的实例,也就是说进程是一个正在运行的程序,程序只是一堆代码,二进制、class字节码或者其他脚本啥的,但进程是一个运行中的实体,包括有程序的运行在内存中的所有资源,比如程序指数器、内存、寄存器、堆栈以及外部的一些资源,比如说USB连接、网络或者磁盘。现代的操作系统一般都是多用户多机的,CPU会调度进程,这是为了提高用户体验度以及充分利用CPU计算资源,因为CPU对进程的切换很快,人根本感觉不到,所有这样就可以使计算机像是在同时运行多个进程一样,这就是所谓的并发,这和并行还是有区别的,并行是真正的同时有多个进程一起运行,这要归功于多核CPU,扯远了,址远了。这往篇blog要讲的是线程,线程可以理解成是进程的一个工作单元,也就是一个真正的工作任务,而其实CPU真正调度的是线程,线程才是真正的并发单元,进程是内存分配的基本单位,一个进程在创建时会向系统申请一个内存区,现在的操作系统一般来说都是实现的虚拟内存技术。我们在进程中申请的内存都来自这个进程的内存,而线程是进程的工作单元,因此所有的线程其实是共享内存,这里说的内存是指堆内存等公用内存,当我们的变量实例在这些公用内存中的时候,所有的线程就都可以访问到,只要进程持有那个内存的引用。而每个线程会有自己的栈内存和程序计数器,但他们是共用堆内存的,因此多个线程访问堆内存中的变量或者说是内存的时候就会出现一些线程同步的问题,比如说脏读等问题,一般来说这些问题都是通过编码中使用锁机制或线程独享变量(或者叫私有变量,也就是让每个线程只能持有自己的变量,其他线程不能访问,就算要共享,也做成多份的,比如用ThreadLocal来实现)来解决。

线程池的概念:为什么要引入线程池?所谓线程池,其实就是用一个集合来保持一定量的线程,当我们要开一个线程的时候,我们不是去创建一个新的线程,而是去线程池中取一个。因为线程是一个比较重量级的组件,创建线程需要很多工作,并且需要占用很多资源,比如会创建线程栈和程序计数器等等,而从先前就创建好的线程中选一个就会大大减少这些不必要的消耗,同时当我们的线程任务结束后线程的资源回收也是一个大的消耗,线程池通过重用线程来提高了资源的重用,这样就可以大大提高程序的性能。而线程池有很多策略,比如固定线程个数,可自动调节线程数等,具体要用哪种策略要分析具体的场景。

下面我们就来自己实现一个简单的固定线程数的线程池

首先,我们需要创建一个线程池的类,这里我们就不设计接口了,

第一个是一个任务接口,实现这个接口来定义我们具体的任务

package com.benson.webserver.core.thread;/** *  任务接口 * author benson * time 2017/11/29 下午1:49 * email 1455813736@qq.com */public interface Task {    void run();}



   第二个是任务线程类,这个类的线程对象会重复使用

package com.benson.webserver.core.thread;/** * 任务线程类 * author benson * time 2017/11/29 下午2:01 * email 1455813736@qq.com */public class WorkThread extends Thread {    private boolean isRun;    private ThreadPool threadPool;    public WorkThread(ThreadPool pool,String name){        isRun = true;        this.threadPool = pool;        setName(name);    }    @Override    public void run() {        while(isRun){            Task run = threadPool.getTask();            if(run==null){continue;}            try {                run.run();            }catch (Exception e){                e.printStackTrace();            }        }    }    public void stopWorkThread(){        isRun = false;    }}


第三个是线程池

package com.benson.webserver.core.thread;import java.util.Collections;import java.util.LinkedList;import java.util.List;/** *  线程池 * author benson * time 2017/11/29 上午11:36 * email 1455813736@qq.com */public class ThreadPool {    private static final int DEFAULT_SIZE = Runtime.getRuntime().availableProcessors()*2;//最大线程数    private int maxSize;//最大线程数    private int length = 0;    private boolean isRun = false;    private WorkThread[] workers;    private List<Task> taskList = Collections.synchronizedList(new LinkedList());    private void init(){        isRun = true;        workers = new WorkThread[maxSize];        for(int i=0;i<maxSize;i++){            workers[i] = new WorkThread(this,"work thread "+i);            workers[i].start();        }    }    public ThreadPool(int size){        this.maxSize = size;        isRun = true;        workers = new WorkThread[maxSize];        for(int i=0;i<maxSize;i++){            workers[i] = new WorkThread(this,"work thread "+i);            workers[i].start();        }    }    public ThreadPool(){        this.maxSize = DEFAULT_SIZE;        init();    }    /**     * 向线程池中添加新任务     * @param task     */    public void addToThreadPool(Task task){        synchronized (taskList){            taskList.add(task);            taskList.notify();        }    }    /**     * 关闭线程池     */    public void closeThreadPool(){        isRun = false;        synchronized (taskList){            taskList.clear();            for(int i=0;i<maxSize;i++){                workers[i].stopWorkThread();            }            taskList.notifyAll();        }    }    public int getTaskLength(){        return length;    }    public Task getTask(){        Task run = null;        if(isRun){            synchronized (taskList){                while (taskList.isEmpty()){                    try {                        taskList.wait();                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                    if(!isRun){                        return null;                    }                }                run = taskList.remove(0);                length++;            }        }        return run;    }}



最后是我们的测试类


package com.benson.webserver.core.thread;/** *  自定义线程池的测试 * author benson * time 2017/11/29 下午2:04 * email 1455813736@qq.com */public class ThreadPoolTest {    public static void main(String[] args){        ThreadPool pool = new ThreadPool(4);        pool.addToThreadPool(new Task() {            @Override            public void run() {                for(int i=0;i<10;i++){                    System.out.println("1 "+i);                    try {                        Thread.sleep(100);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        });        pool.addToThreadPool(new Task() {            @Override            public void run() {                for(int i=0;i<10;i++){                    System.out.println("2 "+i);                }            }        });        try {            Thread.sleep(1000);        } catch (InterruptedException e) {            e.printStackTrace();        }        pool.closeThreadPool();    }}

原创粉丝点击