java技术深入(一)——java多线程(六)——线程池

来源:互联网 发布:淘宝图片空间无法删除 编辑:程序博客网 时间:2024/05/17 19:58

1、线程池好处

首先,由于涉及到与操作系统交互,线程创建是需要付出一定代价的,众多待命的空闲线程随时准备提供服务可以提高效率。如果需要大量的生命期很短的线程,就应该使用线程池。

其次,线城池可以减少并发线程的数量,大量创建线程会大大降低性能,甚至使虚拟机崩溃。如果有一个会创建大量线程的算法,就应该使用线程数固定的线程池以限制并发线程总数

2、线程池如何工作

线程池中可缓存大量随时准备运行的空闲线程。新建线程池对象之后,将Runnable对象交给线程池,就会由其中的一个线程调用run方法。当run方法退出时,线程不会死亡,而是被线程池回收,准备为下一个请求服务。

3、执行器(Executors类)

Executors类提供了许多静态方法来构建各种线程池:


a、newCacheThreadPool:构建一个线程池,线程数目不限。有任务到达时,如果有空闲线程就立即执行任务,没有的话就新建线程。执行任务之后的线程会保留60秒,如果在60秒之内没有接到新任务就销毁线程。

b、newFixedThreadPool:构造一个线程数量固定的线程池,如果提交的任务多于空闲线程数,那么新任务将放置到等待队列中。

c、newSingleThreadExecutor:线程数为1的线程池。

这三个创建线程池的方法均返回一个实现了ExecutorService接口的ThreadPoolExecutor类的对象。调用这个线程池对象的submit方法,传入Runnable对象或者Callable对象,线程池将会在方便的时候执行提交的任务。

当一个线程池不再需要的时候,调用其shutdown函数可以将其安全地关闭。shutdown函数被调用后,线程池对象将不再接受新的任务,等待所有已接受任务完成之后,线程池对象将被销毁。也可以调用shutdownNow方法,该方法意味着取消已接受但尚未执行的任务,尝试中断正在执行的任务,待所有线程关闭后销毁线程池。

4、实例

/ThreadPoolTest/src/IOnCallBack.java

public interface IOnCallBack
{
    public void onCallBack(char c);
}

/ThreadPoolTest/src/MyRunnable.java

public class MyRunnable implements Runnable
{
    private String      str;
    private int         index;
    private IOnCallBack icall;
    public MyRunnable(String _str, int _index, IOnCallBack _icall)
    {
        str = _str;
        index = _index;
        this.icall = _icall;
    }
    @Override
    public void run()
    {
        try
        {
            Thread.sleep(5000);
        } catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        icall.onCallBack(str.toCharArray()[index]);
    }
}

/ThreadPoolTest/src/MyCallable.java文件:

import java.util.concurrent.Callable;
//Callable类似于Runnable接口,实现Runnable、Callable接口的类都可被其他线程异步执行
//Callable和Runnable的区别在于:
//1、Callable定义的方法是call,而Runnable定义的方法是run。
//2、Callable的call方法可以有返回值,而Runnable的run方法不能有返回值。
//3、Callable的call方法可抛出异常,而Runnable的run方法不能抛出异常。  
public class MyCallable implements Callable
{
    private String str;
    private int    index;
    public MyCallable(String _str, int _index)
    {
        str = _str;
        index = _index;
    }
    @Override
    public Object call() throws Exception
    {
        Thread.sleep(5000);
        return str.toCharArray()[index];
    }
}

/ThreadPoolTest/src/Test.java文件:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Test
{
    /**
     * @param args
     */
    public static void main(String[] args)
    {
        ExecutorService pool = Executors.newFixedThreadPool(10);
        MyRunnable run = new MyRunnable("yuyong", 2, new IOnCallBack()
        {
            @Override
            public void onCallBack(char c)
            {
                System.out.println(c + ":run");
            }
        });
        pool.submit(run);
        System.out.println("任务已提交:run");
        // -----------------------------------------------------------------
        ExecutorService pool_single = Executors.newSingleThreadExecutor();
        MyCallable call = new MyCallable("yuyong", 2);
        // Future表示异步计算的结果,它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。
        // Future的cancel方法可以取消任务的执行。它有一布尔参数,参数为true 表示立即中断任务的执行,参数为 false
        // 表示允许正在运行的任务运行完成。
        // Future的 get方法是一个同步方法,调用时会阻塞调用线程等待计算完成,获取计算结果。
        Future f = pool_single.submit(call);
        System.out.println("任务已提交:call");
        try
        {
            System.out.println(((char) f.get()) + ":call");
        } catch (Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

结果如下:













0 0