Java 用线程池实现web服务器

今天在应用中用到了线程池,于是我就想web服务器肯定是用到了线程池,但是他们是怎样实现的呢?于是我就试着写了一个简单的模型

package httpserver;

import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class Main {

    public static void main(String[] args) {
        new Main().startSystem();
    }

    void startSystem(){
    //创建一个固定大小的线程池
        ExecutorService service = Executors.newFixedThreadPool(100);

        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket(80);

            Socket sock = null;

            while((sock=serverSocket.accept()) != null){
                //创建一个线程来处理请求
                SocketHandleThread handleThread = new SocketHandleThread(sock);
                //加入任务队列,等待执行
                service.execute(handleThread);
            }

        } catch (IOException e) {

            e.printStackTrace();
        }
    }
}

class SocketHandleThread extends Thread{

    Socket socket ;

    public SocketHandleThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            OutputStream out = socket.getOutputStream();
            out.write("hello, request handled".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
            // terminate the thread by returnning 
        }
    }
}

   这样的代码是能够处理请求,但是总觉的是有问题的,我的理解是线城市应该是先创建好n个线程,然后要用的时候从池中取一个,然后将某些参数传给该线程,然后就执行了。

    但我这里是每次有请求来都创建一个线程,这样肯定是不行的,太好资源了,不知道到底要怎样搞,再慢慢想吧!大家如果知道,请不吝赐教!在下感激不尽。

============2015年7-28=============
通过网上的文章和自己 的一些思考,终于弄明白了线程池的使用以及我之前的错误是在哪里 ,现在正确的实现方法。

package httpserver;

import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class Main {

    int workerThreadCount = 5;
    WorkerThread [] workerThread = new WorkerThread[workerThreadCount]; 

    LinkedList<SocketTask> taskQueue = new LinkedList<SocketTask>();

    public static void main(String[] args) throws Exception, IOException {

        Main m = new Main();
        m.startWorkerThreads();
        m.startSystem();
    }

    void startWorkerThreads(){

        for(int i = 0 ;i< workerThreadCount;i++){
            workerThread[i] = new WorkerThread(taskQueue);
            workerThread[i].start();
        }
    }

    void startSystem(){
        ExecutorService service = Executors.newFixedThreadPool(100);

        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket(8000);

            Socket sock = null;

            while((sock=serverSocket.accept()) != null){
                //在向任务队列添加任务是需要同步,也就是要获取对象锁
                synchronized (taskQueue){
                    SocketTask sockThread = new SocketTask(sock);
                    taskQueue.add(sockThread);
                    //唤醒一个等待中的worker线程来执行任务队列中的任务
                    taskQueue.notify();
                }


            }

        } catch (IOException e) {

            e.printStackTrace();
        }
    }
}

//工作线程
class WorkerThread extends Thread{

    LinkedList <SocketTask> taskQueue;

    public WorkerThread(LinkedList<SocketTask> taskQueue) {
        this.taskQueue = taskQueue;
    }
    public List<SocketTask> getTaskQueue() {
        return taskQueue;
    }
    public void setTaskQueue(LinkedList<SocketTask> taskQueue) {
        this.taskQueue = taskQueue;
    }


    @Override
    public void run() {
        while(true){
            SocketTask task = null;
            synchronized(taskQueue){
                if(taskQueue.isEmpty()){
                    try {
                        taskQueue.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }else{
                    task = taskQueue.removeFirst();
                }
            }

            if(task != null){
            //直接调用run,并不是启动线程,只是执行了这个对象的run方法,和调用一个类的方法没区别
                task.run();
            }
        }
    }
}

//请注意这个类虽然继承了Thread,但是我们并不是把它作为一个线程来启动的,只是图方便使用了他的run方法,也可以自定义接口,JDK的 线程池也是这样搞的
class SocketTask extends Thread{

    Socket socket ;

    public SocketTask(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {               
            OutputStream out = socket.getOutputStream();
            out.write("hello, request handled  , ^_^ ".getBytes());
            out.flush();
            out.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
            // terminate the thread by returnning 
        }
    }
}

    之前主要的错误是,我以为线程池执行需要的Runnable是一个线程对象,其实不是,你也可以定义为其他的接口,线程在调用时其实是直接调用的run()方法,所以没有启动线程(只有调用start()方法才会启动线程)。

    上面的代码时自己实现了一个 简单的echo server,每次有客户端连接时,向客户端打印一条信息,这里的线程池是自己实现的,这种方式虽然在一定程度上可以正常工作但还是缺少很多功能,可以使用JDK提供的线程池,具有更多的功能,比如拒绝服务 以及更完善的排队队列。


问题1:我有遇到了一个问题,当我在创建ServerSocket时指定了,80端口,这是我本机的apache服务器也在运行,但并没有报错,然后请求被发到了apache服务器,这是什么原因的?求解答哦

补充:关于问题1答案已经找到了,这个问题很值得关注,请参考我的这篇文章 关于ip 0.0.0.0

感谢这篇文章的作者:自己实现线程池
关于线程池详细的参考文章 线程池详细介绍

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值