java多线程之线程池(ExecutorService)

  创建新线程的服务器在创建和销毁线程上花费的时间和消耗的系统资源要比花在处理实际的用户请求的时间和资源更多,线程池为线程生命周期开销问题和资源不足问题提供了解决方案。通过对多个任务重用线程,线程创建的开销被分摊到了多个任务上。 其好处是,因为在请求到达时线程已经存在,所以无意中也消除了线程创建所带来的 延迟。这样,就可以立即为请求服务,使应用程序响应更快。而且,通过适当地调整 线程池中的线程数目,也就是当请求的数目超过某个阈值时,就强制其它任何新到的请求一直等待,直到获得一个线程来处理为止,从而可以防止资源不足。

示例代码:

ThreadPoolTest类:

  1.  
    public class ThreadPoolTest {
  2.  
     
  3.  
    //单一线程数:就是只有一个线程开启,如果多长执行的话就是,这个线程一直轮询执行下去
  4.  
    @SuppressWarnings("unused")
  5.  
    private ExecutorService executorService1 = Executors.newSingleThreadExecutor();
  6.  
    //固定线程数:在程序初始化的时候,虚拟机初始化5个线程
  7.  
    @SuppressWarnings("unused")
  8.  
    private ExecutorService executorService2 = Executors.newFixedThreadPool(5);
  9.  
    //缓存线程数:在程序初始化的时候创建5线程线程,并随着系统的需求增加线程数量,线程数量的上限是系统资源的上线
  10.  
    private ExecutorService executorService3 = Executors.newScheduledThreadPool(5);
  11.  
     
  12.  
    private static int num = 50;
  13.  
    public void threadPool() throws InterruptedException {
  14.  
    //创建了50个线程
  15.  
    for(int i = 0; i < 50; i ++) {
  16.  
     
  17.  
    executorService3.execute(new Runnable() {
  18.  
    public void run() {
  19.  
    try {
  20.  
    Thread.sleep(new Random().nextInt(1700));
  21.  
    } catch (InterruptedException e) {
  22.  
    // TODO Auto-generated catch block
  23.  
    e.printStackTrace();
  24.  
    }
  25.  
    finish();
  26.  
    System.out.println(Thread.currentThread().getName() + "当前剩余任务数量:" + (num));
  27.  
    }
  28.  
    });
  29.  
    }
  30.  
    }
  31.  
    public synchronized void finish() {
  32.  
    num--;
  33.  
    if(num == 0) {
  34.  
    System.out.println("线程池所有任务执行完毕");
  35.  
    }
  36.  
    }
  37.  
    }

Main类:

  1.  
    public class Main {
  2.  
     
  3.  
    public static void main(String[] args) throws Exception {
  4.  
    System.out.println("-----------threadPool测试-----------------");
  5.  
    new ThreadPoolTest().threadPool();
  6.  
    }

测试结果:

可以看到5个线程在执行50个任务,只要线程池里有空闲线程,就会使该线程执行任务。

另外,还可以通过实现Runnable接口,使用线程池ExecutorService的submit方法来向线程池提交任务。

示例代码:

ThreadPoolSubmit类:

  1.  
    public class ThreadPoolSubmit implements Runnable{
  2.  
     
  3.  
    private static int num = 50;
  4.  
     
  5.  
    public void run() {
  6.  
     
  7.  
    try {
  8.  
    Thread.sleep(new Random().nextInt(1700));
  9.  
    } catch (InterruptedException e) {
  10.  
    // TODO Auto-generated catch block
  11.  
    e.printStackTrace();
  12.  
    }
  13.  
    finish();
  14.  
    System.out.println(Thread.currentThread().getName() + "当前剩余任务数量:" + (num));
  15.  
    }
  16.  
     
  17.  
    public synchronized void finish() {
  18.  
    num--;
  19.  
    if(num == 0) {
  20.  
    System.out.println("线程池所有任务执行完毕");
  21.  
    }
  22.  
    }
  23.  
     
  24.  
    public static void main(String[] args) {
  25.  
     
  26.  
    ExecutorService executorService = Executors.newScheduledThreadPool(5);
  27.  
    //50个任务
  28.  
    for (int i = 0; i < 50; i++) {
  29.  
     
  30.  
    executorService.submit(new ThreadPoolSubmit());
  31.  
    }
  32.  
    }
  33.  
     
  34.  
    }

测试结果与上例相同。

posted @ 2018-08-14 09:01  生活百科  阅读(545)  评论(0编辑  收藏  举报