线程池

  • 线程是宝贵的内存资源,单个线程占1MB空间,过多分配易造成内存溢出
  • 频繁的创建及销毁线程会增加虚拟机回收频率、资源开销、造成程序性能下降
  • 因此线程池出现了

线程池的概念

  • 线程容器,可设定线程分配的数量上限
  • 将预先创建的线程对象存入池中,并重用线程池中的线程对象
  • 避免频繁的创建和销毁

线程池的原理




java 线程池如何获取所有运行中的线程 java获取线程执行结果_java线程池


获取线程池


java 线程池如何获取所有运行中的线程 java获取线程执行结果_System_02


创建线程池

public class TestThreadPool {    public static void main(String[] args) {        //  1.  创建固定线程个数的线程池对象        //线程池里可存在4个线程        ExecutorService es = Executors.newFixedThreadPool(4);        //  2.  创建任务        Runnable runnable = new Runnable() {            private int ticket = 100;            @Override            public void run() {                while (true) {                    if(ticket <= 0) {                        break;                    }                    System.out.println(Thread.currentThread().getName() + "买了" + ticket--);                }            }        };        //  3.  提交任务        for(int i = 0; i < 5; i++) {            es.submit(runnable);        }        //  4.  关闭线程池        es.shutdown();    }}

执行结果


java 线程池如何获取所有运行中的线程 java获取线程执行结果_System_03


//  1.  创建单线程的线程池        ExecutorService es = Executors.newSingleThreadExecutor();//  1.  创建缓冲线程池,线程的个数由任务来决定        ExecutorService es = Executors.newCachedThreadPool();

Callable接口

public interface Callable{    public V call() throws Exception;}
  • JDK5加入,与Runnable接口类似,实现之后代表一个线程任务
  • Callable具有泛型返回值、可以声明异常

Future接口

  • 概念:异步接受ExecutorService.submit()所返回的状态结果,当中包含了call()的返回值
  • 方法:V get()以阻塞形式等待Future中的异步处理结果(call()的返回值)

示例

  • 使用Future和Callable接口
  • 使用两个线程,并发计算1-50,51-100的和,再进行汇总
//示例public class TestCallable {    public static void main(String[] args) throws Exception {        //  1.创建线程池对象        ExecutorService es = Executors.newFixedThreadPool(2);        //  2.  提交任务并得到Future对象,任务有Callable匿名对象来承担        Future future1 = es.submit(new Callable() {            @Override            public Integer call() throws Exception {                    //完成1-50的加和运算并得到结果                System.out.println("start 1-50 count...");                int sum = 0;                for(int i = 1; i <= 50; i++) {                    sum += i;                }                return sum;            }        });        Future future2 = es.submit(new Callable() {               @Override            public Integer call() throws Exception {                    //完成51-100的加和运算并得到结果                System.out.println("start 51 - 100 count...");                int sum = 0;                for(int i = 51; i <= 100; i++) {                    sum += i;                }                return sum;            }        });        //  3.  使用Future对象的get()方法得到运算结果        System.out.println("1-100的加和结果为:" + (future1.get() + future2.get()));        //  4.  关闭资源        es.shutdown();    }}

结果


java 线程池如何获取所有运行中的线程 java获取线程执行结果_线程池_04


Lock接口

  • JDK5加入,与synchronized比较,显示定义,结构更灵活
  • 提供更多实用性方法,功能更加强大,性能更优越

常用方法

//获取锁,如锁被占用,则等待void lock()   //尝试获取锁(成功true,失败false,不阻塞)boolean tryLock//释放锁void unlock()
//示例public class TestLock implements Runnable {    Lock l = new ReentrantLock();    private int ticket = 100;    @Override    public void run() {        while (true) {            l.lock();            try {                if(ticket <= 0) {                    break;                }                System.out.println(Thread.currentThread().getName() +  " sells " + ticket--);            } catch (Exception e) {                e.printStackTrace();            }finally {                l.unlock();            }        }    }    public static void main(String[] args) {        ExecutorService es = Executors.newFixedThreadPool(4);        for(int i = 0; i < 4; i++) {            es.submit(new TestLock());        }        es.shutdown();    }}

执行结果


java 线程池如何获取所有运行中的线程 java获取线程执行结果_System_05


线程安全的集合


java 线程池如何获取所有运行中的线程 java获取线程执行结果_线程池_06


Collections中的工具方法


java 线程池如何获取所有运行中的线程 java获取线程执行结果_线程池_07


Queue接口(队列)


java 线程池如何获取所有运行中的线程 java获取线程执行结果_线程池_08


//示例public class TestQueue {    public static void main(String[] args) {        //  1.  创建PriorityQueue队列对象        PriorityQueue q = new PriorityQueue();        //  2.  队列添加元素,“入列”        q.offer("a");        q.offer("b");        q.offer("c");        q.offer("d");        q.offer("e");        //  3.  取值,“出列”        System.out.println(q.poll());        System.out.println(q.poll());        System.out.println(q.poll());        System.out.println(q.poll());        System.out.println(q.poll());    }}

执行结果


java 线程池如何获取所有运行中的线程 java获取线程执行结果_c++ 异步下获取线程执行结果_09