美文网首页程序员java架构经验分享
这份阿里技术官强推的java线程池笔记,建议你看一下,对工作太有

这份阿里技术官强推的java线程池笔记,建议你看一下,对工作太有

作者: 程序员匡胤 | 来源:发表于2020-08-26 20:50 被阅读0次

    线程池

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

    线程池的概念

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

    线程池的原理

    获取线程池

    创建线程池

    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();
        }
    }
    
    

    执行结果

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

    Callable接口

    public interface Callable<V>{
        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<Integer> future1 = es.submit(new Callable<Integer>() {
                @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<Integer> future2 = es.submit(new Callable<Integer>() {   
                @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();
        }
    }
    
    

    结果

    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();
        }
    }
    
    

    执行结果

    线程安全的集合

    Collections中的工具方法

    Queue接口(队列)

    //示例
    public class TestQueue {
    
        public static void main(String[] args) {
    
            //  1.  创建PriorityQueue队列对象
            PriorityQueue<String> q = new PriorityQueue<String>();
    
            //  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线程池笔记,建议你看一下,对工作太有

        本文链接:https://www.haomeiwen.com/subject/jpwfsktx.html