线程池ExecutorService的submit和execute

转载 2015年11月19日 14:43:28

在Java5之后,并发线程这块发生了根本的变化,最重要的莫过于新的启动、调度、管理线程的一大堆API了。在Java5以后,通过 Executor来启动线程比用Thread的start()更好。在新特征中,可以很容易控制线程的启动、执行和关闭过程,还可以很容易使用线程池的特 性。

 

一、创建任务

 

任务就是一个实现了Runnable接口的类。

创建的时候实run方法即可。

 

二、执行任务

 

通过java.util.concurrent.ExecutorService接口对象来执行任务,该接口对象通过工具类java.util.concurrent.Executors的静态方法来创建。

 

Executors此包中所定义的 Executor、ExecutorService、ScheduledExecutorService、ThreadFactory 和 Callable 类的工厂和实用方法。

 

ExecutorService提供了管理终止的方法,以及可为跟踪一个或多个异步任务执行状况而生成 Future 的方法。 可以关闭ExecutorService,这将导致其停止接受新任务。关闭后,执行程序将最后终止,这时没有任务在执行,也没有任务在等待执行,并且无法提交新任 务。

executorService.execute(new TestRunnable());

 

1、创建ExecutorService

通过工具类java.util.concurrent.Executors的静态方法来创建。

Executors此包中所定义的 Executor、ExecutorService、ScheduledExecutorService、ThreadFactory 和 Callable 类的工厂和实用方法。

 

比如,创建一个ExecutorService的实例,ExecutorService实际上是一个线程池的管理工具:

        ExecutorService executorService = Executors.newCachedThreadPool();

        ExecutorService executorService = Executors.newFixedThreadPool(3);

        ExecutorService executorService = Executors.newSingleThreadExecutor();

 

2、将任务添加到线程去执行

当将一个任务添加到线程池中的时候,线程池会为每个任务创建一个线程,该线程会在之后的某个时刻自动执行。

 

示例1:

    @Test

    public void testDemo() throws Exception {

       //单例线程,任意时间(同一时间)池中只能有一个线程

       ExecutorService es = Executors.newSingleThreadExecutor();

       es.execute(new Runnable() {

           @Override

           public void run() {

              System.err.println("线程启动并运行"+Thread.currentThread().getName());

           }

       });

       es.execute(new Runnable() {

           @Override

           public void run() {

              System.err.println("第二个也运行了"+Thread.currentThread().getName());

           }

       });

       //Thread.sleep(1000 * 60 * 60);

    }

运行结果如下:两个都会执行,但程序只会使用一个线程来运行。

线程启动并运行pool-1-thread-1

第二个也运行了pool-1-thread-1

 

示例2:

    @Test

    public void testDemo3() throws Exception {

       //声明一个线程池

       ExecutorService ex = Executors.newCachedThreadPool();

       for (int i = 0; i < 4; i++) {

           final int a = i;

           //每一次execute方法,都是向池中放入一个对象

           ex.execute(new Runnable() {

              public void run() {

                  while(true){

                     System.err.println("测试...."+a+">"

                            +Thread.currentThread().getName()+","

                            +Thread.currentThread().isDaemon());

                     try{

                         Thread.sleep(2000);

                     }catch(Exception e){

                         e.printStackTrace();

                     }

                  }

              }

           });

       }

       Thread.sleep(1000*60*60);

    }
输出的结果如下:从中可以发现,第四个一组输出,即一共创建了四个线程,每次每个线程都会执行输出,但不按顺序:位每一次输出都四个算是一组

测试....0>pool-1-thread-1,false

测试....3>pool-1-thread-4,false

测试....2>pool-1-thread-3,false

测试....1>pool-1-thread-2,false

测试....0>pool-1-thread-1,false

测试....3>pool-1-thread-4,false

测试....2>pool-1-thread-3,false

测试....1>pool-1-thread-2,false

测试....1>pool-1-thread-2,false

测试....2>pool-1-thread-3,false

测试....3>pool-1-thread-4,false

测试....0>pool-1-thread-1,false

 

示例3:

    public void testCall() throws Exception{

       //声明一个类,可以被调用,类似于线程,但它可以拥有返回值

       class MyCall implements Callable<String>{

           private int seq;

           public MyCall(int seq){

              this.seq=seq;

           }

           //抛出异常并可以拥有返回值

           public String call() throws Exception {

              System.err.println("执行"+seq+","+Thread.currentThread().getName());

              Thread.sleep(3000);

              System.err.println("Weak up "+seq);

              return "完成"+seq;//这是返回值

           }

       }

       ExecutorService es = Executors.newCachedThreadPool();//创建线程池对象

       List<Future<String>> result =new ArrayList<Future<String>>();//放结果用的集合

       for(int i=0;i<3;i++){

           Future<String> f=es.submit(new MyCall(i));//线程执行完成以后可以通过引用获取返回值

           result.add(f);

       }

       for(Future<String> f:result){

           System.err.println("返回值:"+f.get());//输出返回的值

       }

       System.err.println("完成....");

    }

一心多用多线程-细谈java线程池submit与execute的区别

深夜学习,发现ThreadPoolExecutor里面一个小知识点,故开热点连wifi怒写submit与execute方法的区别。1.问题的来源在看书的时候,涉及到java线程池问题的时候常常面临这样...
  • hayre
  • hayre
  • 2016年11月24日 01:56
  • 6315

【多线程 5】线程池的类型以及submit()和execute()的区别

就跟题目说的一样,本篇博客,本宝宝主要介绍两个方面的内容,其一:线程池的类型及其应用场景;其二:submit和execute的区别。那么需要再次重申的是,对于概念性的东西,我一般都是从网上挑选截取,再...

线程池的submit和execute的区别

多线程里面还有一个比较有意思的地方就是往线程池中提交线程的时候其实有两种方法 一种是execute另外一种是submit 1. execute提交的方式 execute提交的方式只能提交一个Ru...

浅谈线程池及submit()和execute()的区别

本文主要介绍两个方面的内容,其一:线程池的类型及其应用场景;其二:submit和execute的区别。 一、线程池概述 首先,线程池的使用,是非必须的。并不是涉及到启用多线程的地方,就非得整出个线...

java-源码解读-线程池提交之execute和submit有何不同

先上测试用例 package com.phl.threadpool; import java.util.concurrent.ExecutorService; import java.util.con...

ExecutorService的execute和submit方法

  • 2013年11月12日 23:22
  • 237KB
  • 下载

ExecutorService中submit和execute的区别

在Java5之后,并发线程这块发生了根本的变化,最重要的莫过于新的启动、调度、管理线程的一大堆API了。在Java5以后,通过Executor来启动线程比用Thread的start()更好。在新特征中...

ExecutorService的execute和submit方法

因为之前一直是用的execute方法,最近有个情况需要用到submit方法,所以研究了下。 三个区别: 1、接收的参数不一样 2、submit有返回值,而execute没有 Metho...
  • peachpi
  • peachpi
  • 2011年09月13日 18:09
  • 51918

ExecutorService中submit和execute的区别、Callable 的用法

在Java5之后,并发线程这块发生了根本的变化,最重要的莫过于新的启动、调度、管理线程的一大堆API了。在Java5以后,通过Executor来启动线程比用Thread的start()更好。在新特征中...

ExecutorService常用方法和newFixedThreadPool创建固定大小的线程池

ExecutorService常用方法和newFixedThreadPool创建固定大小的线程池本文由 arthinking 发表于443 天前 ⁄ Java基础 ⁄ 评论数 1 ⁄ 被围观 ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:线程池ExecutorService的submit和execute
举报原因:
原因补充:

(最多只允许输入30个字)