您的位置:首页 > 编程语言 > Java开发

线程池ExecutorService的submit和execute

2015-11-19 14:43 483 查看
在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 线程池 线程 并发