深入理解线程池

创建线程的三种方法:

(1)继承Thread

public class test extends Thread{
    @Override
    public void run(){
        System.out.println("创建成功了么");
    }
    public static void main(String[] args) {
        test a=new test();
        a.start();
    }
}

(2)实现runable接口

public class test implements Runnable{
    @Override
    public void run(){
        System.out.println("创建成功了么");
    }
    public static void main(String[] args) {
        test a=new test();
        new Thread(a).start();
    }
}

(3)实现Callable接口

public class test implements Callable{
    
    public static void main(String[] args) {
        test a=new test();
        FutureTask futureTask=new FutureTask<>(a);
        new Thread(futureTask).start();
        Object su=null;
        try {
            su=futureTask.get();
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println(su);
    }
    @Override
    public Boolean call() throws Exception {
        return null;
    }
}

上述三种方法可以用来创建线程,当然也可以通过线程池创建线程。下述为线程池ThreadPoolExecutor构造函数。Java中也提供了Executors工具类简化线程池的创建过程,但是由于粒度太大,可塑性不强,不推荐。

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

上述代码中,包含了线程池创建的七大参数:核心线程数、最大线程数、阻塞队列、空闲线程存活时间、时间单位、创建线程的工程类、拒绝策略。具体示例如下:

ThreadPoolExecutor threadPoolExecutor=new ThreadPoolExecutor(2, 4, 1000, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10), new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                return new Thread();
            }
}, new ThreadPoolExecutor.AbortPolicy());

进入线程池的execute方法中:

 public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        int c = ctl.get();
        //线程池的线程个数少于corePoolSize则创建新线程执行当前任务
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        //线程个数大于corePoolSize或者创建线程失败,则将任务存放在阻塞队列workQueue中
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        //如果当前任务无法放进阻塞队列中,则创建新的线程来执行任务
        else if (!addWorker(command, false))
            reject(command);
    }

可以通过上述代码看出线程池中线程创建过程,对于许多面试题中提出:如果通过线程池知道一个线程是否已经完成。对于这个问题的解答,可以通过线程池的另一个运行方法submit(),此方法提供了一个Future的返回值,可以通过Future.get()方法获取任务的返回值。和execute相比,execute只能提交Runnable类型的任务,无返回值。submit既能提交Runnable类型的任务,返回值为null,也能提交Callable类型的任务,返回值为Future。如下所示

FutureTask futureTask1= (FutureTask) threadPoolExecutor.submit(new Callable() {
            @Override
            public Boolean call() throws Exception {
                return null;
            }
        });
        Object ob=futureTask1.get();

看到submit源码,其内部也会使用execute来创建。

public  Future submit(Callable task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture ftask = newTaskFor(task);
        execute(ftask);
        return ftask;
    }

你可能感兴趣的:(java,开发语言)