这里推荐大家上http://www.ibm.com/developerworks/cn/java看java的知识,ibm做的文档还是很不错
线程池启动顺序:::其实线程池说白了,就是先创建好一个池子(就是线程数组),然后启动每个线程(每个线程先询问任务队列(一个链表),查看队列里是否有任务,如果没有,则wait(),醒来的时候在判断任务队列,这里用wait是因为睡着后它能够十分锁定资源),刚开始的时候都因为没有任务而进入阻塞状态,如果有任务加入,用Notify来唤醒线程,线程执行结束后,又进入循环等待任务,这个过程就是一个线程池的思想。大家会想,建立好这么多线程会不会浪费资源呢?这里对模拟了一个500个线程访问的过程,而实际只是用了30个线程开启,见下文。
因为每个线程处理时间不长,如果我们是按照来一个请求才创建一个线程,(1)那么服务器大部分的都是用来创建和销毁线程以及线程管理,这使得服务器使用效率低,(2)而且有多少服务就产生多少线程,这对于服务器来说是十分可怕的,虽然现在内存都大的足够了。。
当然也有不足,比如多用户请求同时来到时候,对于大于线程数的多余请求就会进入任务队列等待,在用户体验上稍微有些不足,但是这种影响是十分小的,只要我们的线程池大小设置的刚好,足以满足了。
好了 话不多说,大家记住线程池的启动顺序!
这里nThreads的取值很重要:这个阈值应该根据实际最大最小线程数来定
Threads就是存储线程的线程池,需要的时候拿出来执行runnable.run()
Queue这个队列很重要,如果线程池满了,则需要这个队列来存放线程,当有线程空闲的时候从这里取出。
下面我就此进行了一个简单测试,如果不采用线程池,则每创建一个线程,执行完任务就销毁。
Main.java
package com.ylf; public class Main { public static int count; public static void main(String[] args) { int nThreads = 500; count=0; //先测试以往情况 long time = System.currentTimeMillis(); for(;nThreads>0;nThreads--) { MyThread r = new MyThread(); Thread t = new Thread(r); t.start(); } while(count!=500) ;//这里是等待所有的线程都处理结束 time = System.currentTimeMillis() - time; System.out.println("time:" + time + "\ncount:" + count); // //线程池测试 nThreads = 500; count=0; long time2 = System.currentTimeMillis();// WorkQueue w = new WorkQueue(30); for(;nThreads>0;nThreads--) { MyThread r2 = new MyThread(); w.execute(r2); } while(count!=500) ; time2 = System.currentTimeMillis() - time2; System.out.println("time2:" + time2 + "\ncount:" + count); w.clean(); } } |
MyThread.java 模拟每个线程任务,取名为Task更好。。。
package com.ylf;
public class MyThread implements Runnable { @Override public void run() { // for(int i=0; i<10; i++){ // ; // } try { Thread.sleep(2); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Main.count++; } } |
线程池队列
package com.ylf; import java.util.LinkedList; public class WorkQueue { private int nThreads; private ThreadPool[] threads; private LinkedList queue; public WorkQueue(int nThreads) { this.nThreads = nThreads; threads = new ThreadPool[nThreads]; queue = new LinkedList(); //创建好线程池,并且让这些线程进入等待任务状态 for(int i = 0; i threads[i] = new ThreadPool(); threads[i].start(); } } public void execute(Runnable r){ synchronized (queue) { queue.addLast(r); queue.notify(); } } public void clean(){ for(int i=0; i<</span>nThreads; i++){ threads[i].stop(); } } public class ThreadPool extends Thread{ @Override public void run() { Runnable r = null; while (true) { synchronized (queue) { while (queue.isEmpty()) { try { queue.wait(); } catch (InterruptedException e) { e.printStackTrace(); } }//while end r = queue.removeFirst(); }//synchronized end //这里只调用方法形式调用run()即可,但是不能放到同步块里,否则占用资源 r.run(); }//while end } } } |
执行结果:
time:178 count:500 time2:66
time:100 count:500 time2:43
time:149 count:500 time2:49 count:500 每次结果不太一样,但是效果很明显 |