要求是打印用户输入的字符串,用户输入一个字符串就创建一个线程去打印他,用户不断输入,就不断创建,当池中线程数量达到池的容量后提示用户池满了,请等等。

解决方案 »

  1.   

    一个Socket和线程池的简单代码,和你的要求差不多,参考一下吧Handler.javaimport java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.Socket;
    import java.util.Date;
    import java.util.Vector;public class Handler extends Thread {
    private Vector<Socket> taskQueue;
    public Handler(Vector<Socket> taskQueue,String threadName) {
    super(threadName);
    this.taskQueue = taskQueue;
    }
    @Override
    public void run() {
    /*
     * 这里使用一个死循环,保证线程完成它所分配的任务后
     * 继续回到线程池中等待分配新的任务
     * 从而实现线程重利用
     */
    while(true){
    Socket socket = null;
    synchronized(taskQueue){
    /*
     * 如果没有排列等候的任务,所有线程一直等待
     */
    while(taskQueue.isEmpty()){
    try {
    /*
     * 一个对象调用它的wait()方法时,它会首先释放它的锁
     * 然后导致当前线程等待
     * 这个时候,等待taskQueue对象的锁
     * 的线程会得到锁,进入同步块,运行到这里时,该线程也释放锁,等待。。
     * 直到另外一个线程,调用taskQueue.notifyAll()方法,
     * 所有在这里等待的线程,就会让taskQueue试着去得到它的锁,
     * 如果得到了锁,才会往下执行。否则一直等待。
     */
    taskQueue.wait();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    /*
     * 任务队列中出现任务,弹出尾部的任务,保证先进先出顺序
     */
    socket = taskQueue.remove(taskQueue.size()-1);
    }

    try {
    InputStream in = socket.getInputStream();
    BufferedReader reader = new BufferedReader(new InputStreamReader(in));
    String strline = null;
    while((strline=reader.readLine())!=null){
    System.out.println(Thread.currentThread().getName()+" 处理了请求 "+strline);
    }
    reader.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }

    }Server.javaimport java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.Vector;public class Server {
    private static final int PORT = 9999;

    public static void main(String[] args) {
    /*使用Vector实现任务队列,
     *因为它是同步的,而且是一种线性的数据结构,
     *实现队列非常方便
     * */
    Vector<Socket> taskQueue = new Vector<Socket>();
    /*
     * 在服务器启动的时候就去启动 线程池中的线程
     * 让它们去等待分配任务
     */
    Handler[] handlers = new Handler[5];
    for(int i=0;i<handlers.length;i++){
    handlers[i] = new Handler(taskQueue,"线程"+i);
    System.out.println("线程"+i+" start...");
    handlers[i].start();
    }
    try {
    ServerSocket serverSocket = new ServerSocket(PORT);
    while(true){
    Socket socket = serverSocket.accept();
    /*
     * 注意,wait(),notify(),notifyAll()方法都需要放在同步块当中
     * 因为一个对象调用它的这些方法,首先要得到对象的锁
     */
    synchronized(taskQueue){
    /*
     * 将任务放在集合的头部
     * 在线程中取出时,弹出是的尾部的任务
     * 这样保证先进先出的任务队列
     * */
    taskQueue.add(0,socket);
    /*
     * 通知线程池中等待taskQueue对象的锁的所有线程
     */
    taskQueue.notifyAll();
    }

    }
    } catch (IOException e) {
    e.printStackTrace();

    }}
    Client.javaimport java.io.BufferedWriter;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.net.Socket;
    import java.net.UnknownHostException;
    import java.util.UUID;public class Client {

    public static void main(String[] args) {
    /*
     * 和服务器连接五十次,模拟多客户请求
     */
    for(int i=0;i<50;i++){
    try {
    Socket socket = new Socket("127.0.0.1",9999);
    OutputStream output = socket.getOutputStream();
    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output));
    writer.write(UUID.randomUUID().toString());
    writer.close();
    socket.close();
    } catch (UnknownHostException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    }}
      

  2.   

    可不可以不要用socket这个东西啊。。我不懂啊。。我才刚开始学习多线程,尽量写简单一点的嘛
      

  3.   


    看楼主头像,我只想对lz说,少打一会dota或者wow研究一下,就什么都明白了。
      

  4.   

    你自己想实现一个线程池?涉及到“池”的东西,不管是实例池、数据库连接池,还是线程池,他们的实现都是极其复杂的。如果不是精于这些东西的话,要想实现并且能运用在实际中,那就是不可能的任务。线程池的实现,我粗粗地列举了一下,以如下技术难点:1:如果不是使用 java.util.concurrent.LinkedBlockingQueue 的话,那就需要自行实现一个阻塞的有界或者无界队列,用于存放等待的任务2:线程池中的线程在运行时产生异常且处理不当,这时将会产生线程泄漏,也就是说线程池中的线程少了一个。一个可用的线程池在监测到这种情况出现时应该回收该泄漏的线程,并及时补充一个新的线程3:线程池中的线程都在工作时,若还有任务加入进来,这时需要将其放入到队列之中,若池中的某个线程工作完了,需要及时通知队列中的任务附加到可用线程中去执行-----------------------------------------------------------------------
    线程池基本上是这样实现的:1:先 new 出固定数量的 Thread,类似于这样:Thread t0 = new Thread(new WorkRunnable());WorkRunnable 的结构基本上是这样的(实际远远比这复杂):public class WorkRunnable implements Runnable {    private Runnable command;    public WorkRunnable(Runnable command) {
            this.command = command;
        }    public void run() {
            command.run();
        }    public void setCommand(Runnable command) {
            this.command = command;
        }
    }2:执行 t0.start() 可以执行线程,如果执行完了,将 WorkRunnable 中的 command 换一个再 start() 又可以执行了。基本上的思路就是这样,但是实现起来极其复杂,不建议自己写,了解一下就可以了。
      

  5.   

    线程池的话,还是使用现成的 java.util.concurrent.ThreadPoolExecutor 吧,自己要实现的话,你和我都不可能完成!
      

  6.   


    public static void main(String[] args) {
    int threadMax = 5;
    ThreadPoolExecutor executor =  
    new ThreadPoolExecutor(2,threadMax,3,TimeUnit.SECONDS, new  ArrayBlockingQueue(3),new ThreadPoolExecutor.CallerRunsPolicy());
    Scanner sc = new Scanner(System.in);
    while(true){
    System.out.println("请输入:");
    final String s = sc.nextLine();
    if(threadMax == executor.getActiveCount()){
    System.out.println("线程满请稍后输入数据");
    try {
    Thread.sleep(2000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    } else{
    executor.execute(new Runnable(){
    public void run(){
    try {
    Thread.sleep(5000);
    System.out.println("s:" + s);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    });
    }
    }
    }