• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Java > java线程池详解

java线程池详解

作者:Don't worry,be happy 字体:[增加 减小] 来源:互联网 时间:2017-09-12

Don't worry,be happy通过本文主要向大家介绍了java,线程池,并发等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

new Thread 的弊端

首先看一段代码:

/**
 * Created by Zero on 2017/8/30.
 */
public class ThreadTest {
    public static void main(String[] args) {
        while (true) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread());
                }
            }).start();
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
Thread[Thread-0,5,main]
Thread[Thread-4,5,main]
Thread[Thread-3,5,main]
Thread[Thread-6,5,main]
Thread[Thread-7,5,main]
Thread[Thread-2,5,main]
Thread[Thread-1,5,main]
Thread[Thread-8,5,main]
Thread[Thread-9,5,main]
Thread[Thread-5,5,main]
Thread[Thread-10,5,main]
Thread[Thread-11,5,main]
Thread[Thread-12,5,main]
Thread[Thread-13,5,main]
... ...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

先说一下此处的打印,第一个参数是当前线程名称,由于线程之间是异步执行,有的还没创建好,有的后来居上就执行完了,导致打印线程的名称会这样,第二个参数是优先级,默认都是5,第三个参数是线程组名称。

如果不停止程序,这段代码会不断创建和销毁线程,直到死机或者OOM,更尴尬的是此处的线程,还无法主动去中断。

上述的线程启动方式在日常开发中经常看到的,但是从性能和优化的角度来说,问题还真不小。

  1. 每次都新建,性能较差(这个在线程池原理中有详细讲解)。
  2. 线程缺乏统一管理,可能无限制的创建线程,互相竞争,会带来一些不必要的麻烦。
  3. 可控性太差,比如定时定期执行,比如线程中断机制。

线程池的优点

java提供了四大线程池,主要针对new Thread的弊端讲述优点:

  1. 降低资源消耗,不需要每次都是新建和销毁,性能得到了提高。
  2. 统一管理,可有效控制最大并发量,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
  3. 可控性很好,可以定期定时执行、线程中断机制等。

newCachedThreadPool

newCachedThreadPool:创建带有缓存的线程池。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by Zero on 2017/8/30.
 */
public class ThreadTest {
    public static void main(String[] args) {
        test();
    }

    private static void test(){
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        for (int i = 0; i < 100; i++) {

            cachedThreadPool.execute(new Runnable() {

                @Override
                public void run() {
                    System.out.println(Thread.currentThread());
                }
            });
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
Thread[pool-1-thread-2,5,main]
Thread[pool-1-thread-4,5,main]
Thread[pool-1-thread-3,5,main]
Thread[pool-1-thread-6,5,main]
Thread[pool-1-thread-1,5,main]
Thread[pool-1-thread-5,5,main]
Thread[pool-1-thread-7,5,main]
Thread[pool-1-thread-7,5,main]
Thread[pool-1-thread-5,5,main]
Thread[pool-1-thread-3,5,main]
Thread[pool-1-thread-4,5,main]
Thread[pool-1-thread-7,5,main]
Thread[pool-1-thread-6,5,main]
Thread[pool-1-thread-4,5,main]
... ...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

由此可见,上述线程在新建的同时,还有部分线程被回收后再利用,刚刚做了下测试,在每次打印之前加了2ms的延迟,打印的都是“Thread[pool-1-thread-1,5,main]”。

线程池为无限大(其实是Interger. MAX_VALUE),当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

newFixedThreadPool

newFixedThreadPool:创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by Zero on 2017/8/30.
 */
public class ThreadTest {
    public static void main(String[] args) {
        test();
    }

    private static void test(){
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 100; i++) {

            fixedThreadPool.execute(new Runnable() {

                @Override
                public void run() {
                    System.out.println(Thread.currentThread());
                }
            });
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
Thread[pool-1-thread-2,5,main]
Thread[pool-1-thread-3,5,main]
Thread[pool-1-thread-1,5,main]
Thread[pool-1-thread-3,5,main]
Thread[pool-1-thread-3,5,main]
Thread[pool-1-thread-2,5,main]
Thread[pool-1-thread-3,5,main]
Thread[pool-1-thread-1,5,main]
Thread[pool-1-thread-2,5,main]
Thread[pool-1-thread-3,5,main]
Thread[pool-1-thread-1,5,main]
Thread[pool-1-thread-3,5,main]
Thread[pool-1-thread-2,5,main]
... ...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

此处配置最大的线程长度是3,由打印可看出,此处始终在三个线程中执行。

newScheduledThreadPool

newScheduledThreadPool:支持定时和周期性执行的线程池。

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * Created by Zero on 2017/8/30.
 */
public class ThreadTest {
    public static void main(String[] args) {
        test();
    }

    private static void test(){
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
        /**
         * 延迟3秒执行
         */
        scheduledThreadPool.schedule(new Runnable() {

            @Override
            public void run() {
                System.out.println(Thread.currentThread());
            }
        }, 3000, TimeUnit.MILLISECONDS);

        /**
         * 延迟1秒后每3秒执行一次
         */
        scheduledThreadPool.scheduleAtFixedRate(new Runnable() {

            @Override
            public void run() {
                System.out.println(Thread.currentThread());
            }
        }, 1, 3000, TimeUnit.MILLISECONDS);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
Thread[pool-1-thread-1,5,main]
Thread[pool-1-thread-1,5,main]
Thread[pool-1-thread-2,5,main]
Thread[pool-1-thread-1,5,main]
Thread[pool-1-thread-1,5,main]
Thread[pool-1-thread-1,5,main]
Thread[pool-1-thread-1,5,main]
Thread[pool-1-thread-1,5,main]
Thread[pool-1-thread-1,5,main]
Thread[pool-1-thread-1,5,main]
Thread[pool-1-thread-1,5,main]
Thread[pool-1-thread-2,5,main]
Thread[pool-1-thread-2,5,main]
... ...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

此方法无论任务执行时间长短,都是当第一个任务执行完成之后,延迟指定时间再开始执行第二个任务。

在日常开发中,newScheduledThreadPool可以作为timer的替代品,对比timer,newScheduledThreadPool更安全更强大。

newSingleThreadExecutor

newSingleThreadExecutor:从名称上便可以看出,此线程池是一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序。如果这个线程异常结束,会有另一个取代它,保证顺序执行。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by Zero on 2017/8/30.
 */
public class ThreadTest {
    public static void main(String[] args) {
        test();
    }

    private static void test(){
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 100; i++) {
            singleThreadExecutor.execute(new Runnable() {

                @Override
                public void run() {
                    System.out.println(Thread.currentThread());
                }
            });
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

得到的结果会一直是“Thread[pool-1-thread-1,5,main]”。

总结:对于任务量少或者只有一个任务的情况下,此时使用线程池显得高射炮打蚊子了,但是对于任务量多,单个任务处理的时间比较短的情况下,你会对线程池有不一样的体会和好感。

 

转自:http://blog.csdn.net/pangpang123654/article/details/77720036

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • JavaThreadPoolExecutor线程池调度器
  • 全面掌握Java内部类
  • Java中的常用阻塞队列源码分析
  • Java虚拟机(四)垃圾收集算法
  • Java内存模型与线程
  • Java中如何优雅正确的终止线程
  • [译]深入字节码操作:使用ASM和Javassist创建审核日志
  • IntelliJIDEA平台下JNI编程(五)—本地C代码创建Java对象及引用
  • 【java总结】设计模式详解
  • Java代码中常见技术债务处理之Exception

相关文章

  • 2017-05-28SpringBoot拦截器实现对404和500等错误的拦截
  • 2017-05-28Java定时任务详解
  • 2017-05-28Spring Boot实现文件上传示例代码
  • 2017-05-28JAVA面试题之Forward与Redirect的区别详解
  • 2017-05-28Spring Boot中使用jdbctemplate 操作MYSQL数据库实例
  • 2017-05-28java 文件大数据Excel下载实例代码
  • 2017-09-13HashMap底层实现原理/HashMap与HashTable区别/HashMap与HashSet区别
  • 2017-05-28基于SpringBoot与Mybatis实现SpringMVC Web项目
  • 2017-05-28java实现将汉语转换为拼音功能
  • 2017-05-28java IO 文件操作方法总结

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • Struts2实现文件上传时显示进度条功能
    • java仿Servlet生成验证码实例详解
    • SWT(JFace)体验之复制粘贴
    • 详解Spring-Boot集成Spring session并存入redis
    • Java定时器例子_动力节点Java学院整理
    • SpringBoot(十)之邮件服务
    • Java中正则表达式的使用和详解(上)
    • 详解JDBC使用
    • Java 中Timer和TimerTask 定时器和定时任务使用的例子
    • Mybatis开发环境搭建实现数据的增删改查功能

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有