zoukankan      html  css  js  c++  java
  • 多线程(三)

    接着说 线程池,使用java自带的线程池,一般的情况下线程池对应的实现类是ThreadPoolExecutor,当然不排除自己来写一个线程池,扯远了,ThreadPoolExecutor 扩展自抽象类AbstractExecutorService,其中AbstractExecutorService 默认的实现了:

    image

    默认的实现的方法中首先我们看看,上面我们说到的submit()方法:

    源代码:

    public Future<?> submit(Runnable task) {
            if (task == null) throw new NullPointerException();
            RunnableFuture<Object> ftask = newTaskFor(task, null);
            execute(ftask);
            return ftask;
        }
    
        public <T> Future<T> submit(Runnable task, T result) {
            if (task == null) throw new NullPointerException();
            RunnableFuture<T> ftask = newTaskFor(task, result);
            execute(ftask);
            return ftask;
        }
    
        public <T> Future<T> submit(Callable<T> task) {
            if (task == null) throw new NullPointerException();
            RunnableFuture<T> ftask = newTaskFor(task);
            execute(ftask);
            return ftask;
        }

    可以看到的是:

    针对submit()接受的参数的类型是实现了Runable 或者Callable 接口的类,然后封装为 RunnableFuture<T> ftask = newTaskFor(task);  交给execute(ftask)执行,返回执行的结果。这个execute(Runnable)方法将在子类ThreadPoolExecutor中实现。

    我们可以首先来看一下executor接口的说明:

    public interface Executor {
    
        /**
         * Executes the given command at some time in the future.  The command
         * may execute in a new thread, in a pooled thread, or in the calling
         * thread, at the discretion of the <tt>Executor</tt> implementation.
         *
         * @param command the runnable task
         * @throws RejectedExecutionException if this task cannot be
         * accepted for execution.
         * @throws NullPointerException if command is null
         */
        void execute(Runnable command);
    }

    在将来某个时刻执行给定的任务command,说明这个方法是将来会去执行,在主线程(submit方法)中是不会阻塞的。另外,注意到如果提交的是Runnable接口,返回的future对象中其结果是在任务提交时候就指定了的,要么是null,要么是T result。上面的分析可以简单测试下:

    //Callable 任务
    class CallabelTask implements Callable<String>{
            String name;
            public CallabelTask(String name){
                this.name = name;
            }
            @Override
            public String call() throws Exception {
                System.out.println("Start to execute the task " + name);
                TimeUnit.SECONDS.sleep(5);
                return name + " is done!";
            }
            
        }
    public static void submitCallableTask()throws Exception{
            ExecutorService executor = Executors.newCachedThreadPool();
            List<Future<String>> results = new ArrayList<Future<String>>(5);
            for(int i = 0; i < 5; ){
                results.add(executor.submit(new CallabelTask("task_"+(++i))));
            }
            System.out.println("All the tasks have been submited through invokeAll method!");
            executor.shutdown();
            for(Future<String> f : results)
                System.out.println(f.get());
        }
    public static void main(String[] args) throws Exception { submitCallableTask();
    }
    //调用submitCallableTask的结果:
    All the tasks have been submited through invokeAll method!
    Start to execute the task task_1
    Start to execute the task task_5
    Start to execute the task task_3
    Start to execute the task task_4
    Start to execute the task task_2
    task_1 is done!
    task_2 is done!
    task_3 is done!
    task_4 is done!
    task_5 is done!

    从返回的结果看,主线程在执行完executor.submit(new CallabelTask("task_"+(++i))) 之后并没有阻塞,而是继续往下执行println语句打印出语句:

    All the tasks have been submited through invokeAll method!

    而提交的任务将由其他线程在“将来某个时刻“去执行。当然在主线程去获取执行结果f.get() 的时候肯定是要阻塞的,因为既然要获取结果了,当然要等到任务执行完毕返回才有啊!

    如果把上面的CallabelTask改变成RunnableTask,则返回的结果将是null,原因是提交的时候在new TaskFor方法中就已经指定了返回结果为null,就是上面的submit源代码中的这句话:

    RunnableFuture<Object> ftask = newTaskFor(task, null);

    测试的代码是:

    class RunnableTask implements Runnable{
            String name;
            public RunnableTask(String name){
                this.name = name;
            }
            @Override
            public void run() {
                System.out.println("Start to execute the task " + name);
                try {
                    TimeUnit.SECONDS.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    //RunnableTask 执行结果:
    All the tasks have been submited through invokeAll method!
    Start to execute the task task_1
    Start to execute the task task_5
    Start to execute the task task_3
    Start to execute the task task_4
    Start to execute the task task_2
    null
    null
    null
    null
    null
  • 相关阅读:
    Python 安装Twisted 提示python version 2.7 required,which was not found in the registry
    Openfire Strophe开发中文乱码问题
    css div 垂直居中
    How to create custom methods for use in spring security expression language annotations
    How to check “hasRole” in Java Code with Spring Security?
    Android 显示/隐藏 应用图标
    Android 当媒体变更后,通知其他应用重新扫描
    文件上传那些事儿
    专题:点滴Javascript
    主流动画实现方式总结
  • 原文地址:https://www.cnblogs.com/zhailzh/p/3972917.html
Copyright © 2011-2022 走看看