合理利用线程池能够带来三个好处
  1. 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
  2. 提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
  3. 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

官方建议使用Executors工厂类来创建线程池对象

使用newCachedThreadPool()方法创建无界线程池

使用Executors类的newCachedThreadPool()方法创建的是无界线程池,可以进行线程自动回收。所谓的“无界线程池”就是池中存放线程个数理论上是Integer.MAX_VALUE。

public class Run1 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(new Runnable() { @Override
public void run() {
try {
System.out.println("Runnable1 begin:" + System.currentTimeMillis());
Thread.sleep(1000);
System.out.println("A");
System.out.println("Runnable1 end:" + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
executorService.execute(new Runnable() { @Override
public void run() {
try {
System.out.println("Runnable2 begin:" + System.currentTimeMillis());
Thread.sleep(1000);
System.out.println("A");
System.out.println("Runnable2 end:" + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}

程序运行结果如下:

Runnable1 begin:1470228063076
Runnable2 begin:1470228063076
A
A
Runnable2 end:1470228064081
Runnable1 end:1470228064081

线程池的线程复用效果
public class MyRunnable implements Runnable {
private String username;
public MyRunnable(String username) {
super();
this.username = username;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " username=" + username + " begin:" + System.currentTimeMillis());
System.out.println(Thread.currentThread().getName() + " username=" + username + " end:" + System.currentTimeMillis());
}
} public class Main {
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++) {
executorService.execute(new MyRunnable("" + i));
}
Thread.sleep(2000);
System.out.println();
for (int i = 0; i < 5; i++) {
executorService.execute(new MyRunnable("" + i));
}
}
}

程序运行结果如下:

pool-1-thread-1 username=0 begin:1470229448635
pool-1-thread-4 username=3 begin:1470229448635
pool-1-thread-3 username=2 begin:1470229448635
pool-1-thread-2 username=1 begin:1470229448635
pool-1-thread-3 username=2 end:1470229448635
pool-1-thread-4 username=3 end:1470229448635
pool-1-thread-5 username=4 begin:1470229448635
pool-1-thread-1 username=0 end:1470229448635
pool-1-thread-5 username=4 end:1470229448636
pool-1-thread-2 username=1 end:1470229448635 pool-1-thread-1 username=2 begin:1470229450637
pool-1-thread-3 username=4 begin:1470229450637
pool-1-thread-3 username=4 end:1470229450637
pool-1-thread-2 username=0 begin:1470229450637
pool-1-thread-2 username=0 end:1470229450638
pool-1-thread-5 username=1 begin:1470229450637
pool-1-thread-4 username=3 begin:1470229450637
pool-1-thread-4 username=3 end:1470229450638
pool-1-thread-5 username=1 end:1470229450638
pool-1-thread-1 username=2 end:1470229450637

由打印结果可见,第一次for循环中创建了5个线程对象分别是pool-1-thread-1到pool-1-thread-5,第二次for循环中没有创建新的线程对象,复用了第一次for循环中创建的线程对象。


使用newCachedThreadPool(ThreadFactory)定制线程工厂
public class MyThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setName("定制池中线程对象的名称" + Math.random());
return thread;
}
} public class Run {
public static void main(String[] args) {
MyThreadFactory myThreadFactory = new MyThreadFactory();
ExecutorService executorService = Executors.newCachedThreadPool(myThreadFactory);
executorService.execute(new Runnable() { @Override
public void run() {
System.out.println(Thread.currentThread().getName() + "运行:" + System.currentTimeMillis());
}
});
}
}

程序运行结果如下:

定制池中线程对象的名称0.2671917944865071运行:1470230269473

使用newFixedThreadPool(int)方法创建有界线程池
public class MyRunnable implements Runnable {
String username;
public MyRunnable(String username) {
super();
this.username = username;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " username=" + username + " begin:" + System.currentTimeMillis());
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + " username=" + username + " end:" + System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
}
}
} public class Run {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 0; i < 3; i++) {
executorService.execute(new MyRunnable("" + i));
}
for (int i = 0; i < 3; i++) {
executorService.execute(new MyRunnable("" + i));
}
}
}

程序运行结果如下:

pool-1-thread-1 username=0 begin:1470230865037
pool-1-thread-3 username=2 begin:1470230865037
pool-1-thread-2 username=1 begin:1470230865037
pool-1-thread-3 username=2 end:1470230867043
pool-1-thread-1 username=0 end:1470230867042
pool-1-thread-3 username=0 begin:1470230867043
pool-1-thread-1 username=1 begin:1470230867043
pool-1-thread-2 username=1 end:1470230867043
pool-1-thread-2 username=2 begin:1470230867043
pool-1-thread-3 username=0 end:1470230869047
pool-1-thread-1 username=1 end:1470230869047
pool-1-thread-2 username=2 end:1470230869047

此时线程池中最多有三个线程。


使用newFixedThreadPool(int, ThreadFactory)定制线程工厂
public class MyThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setName("定制池中线程对象的名称" + Math.random());
return thread;
}
} public class Run {
public static void main(String[] args) {
MyThreadFactory threadFactory = new MyThreadFactory();
ExecutorService executorService = Executors.newFixedThreadPool(2, threadFactory);
Runnable runnable = new Runnable() { @Override
public void run() {
try {
System.out.println("begin 我在运行" + System.currentTimeMillis() + " " + Thread.currentThread().getName());
Thread.sleep(2000);
System.out.println("end 我在运行" + System.currentTimeMillis() + " " + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
} }
};
executorService.execute(runnable);
executorService.execute(runnable);
executorService.execute(runnable);
}
}

程序运行结果如下:

begin 我在运行1470231214770 定制池中线程对象的名称0.07643716796315236
begin 我在运行1470231214770 定制池中线程对象的名称0.5060032203497645
end 我在运行1470231216773 定制池中线程对象的名称0.5060032203497645
end 我在运行1470231216773 定制池中线程对象的名称0.07643716796315236
begin 我在运行1470231216773 定制池中线程对象的名称0.5060032203497645
end 我在运行1470231218774 定制池中线程对象的名称0.5060032203497645

使用newSingleThreadExecutor()方法创建单一线程池
public class MyRunnable implements Runnable {
String username;
public MyRunnable(String username) {
super();
this.username = username;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " username=" + username + " begin:" + System.currentTimeMillis());
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + " username=" + username + " end:" + System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
}
}
} public class Run {
public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
for (int i = 0; i < 3; i++) {
executorService.execute(new MyRunnable("" + i));
}
}
}

程序运行结果如下:

pool-1-thread-1 username=0 begin:1470231470978
pool-1-thread-1 username=0 end:1470231472978
pool-1-thread-1 username=1 begin:1470231472978
pool-1-thread-1 username=1 end:1470231474982
pool-1-thread-1 username=2 begin:1470231474982
pool-1-thread-1 username=2 end:1470231476984

此时线程池中只有一个线程。

newSingleThreadExecutor(ThreadFactory) 使用方法与前面的大体一致。

Java并发编程核心方法与框架-Executors的使用的更多相关文章

  1. Java并发编程核心方法与框架-CountDownLatch的使用

    Java多线程编程中经常会碰到这样一种场景:某个线程需要等待一个或多个线程操作结束(或达到某种状态)才开始执行.比如裁判员需要等待运动员准备好后才发送开始指令,运动员要等裁判员发送开始指令后才开始比赛 ...

  2. Java并发编程核心方法与框架-TheadPoolExecutor的使用

    类ThreadPoolExecutor最常使用的构造方法是 ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAli ...

  3. Java并发编程核心方法与框架-Fork-Join分治编程(一)

    在JDK1.7版本中提供了Fork-Join并行执行任务框架,它的主要作用是把大任务分割成若干个小任务,再对每个小任务得到的结果进行汇总,这种开发方法也叫做分治编程,可以极大地利用CPU资源,提高任务 ...

  4. Java并发编程核心方法与框架-CompletionService的使用

    接口CompletionService的功能是以异步的方式一边生产新的任务,一边处理已完成任务的结果,这样可以将执行任务与处理任务分离.使用submit()执行任务,使用take取得已完成的任务,并按 ...

  5. Java并发编程核心方法与框架-Semaphore的使用

    Semaphore中文含义是信号.信号系统,这个类的主要作用就是限制线程并发数量.如果不限制线程并发数量,CPU资源很快就会被耗尽,每个线程执行的任务会相当缓慢,因为CPU要把时间片分配给不同的线程对 ...

  6. Java并发编程核心方法与框架-ScheduledExecutorService的使用

    类SchedukedExecutorService的主要作用是可以将定时任务与线程池功能结合. 使用Callable延迟运行(有返回值) public class MyCallableA implem ...

  7. Java并发编程核心方法与框架-ExecutorService的使用

    在ThreadPoolExecutor中使用ExecutorService中的方法 方法invokeAny()和invokeAll()具有阻塞特性 方法invokeAny()取得第一个完成任务的结果值 ...

  8. Java并发编程核心方法与框架-Future和Callable的使用

    Callable接口与Runnable接口对比的主要优点是Callable接口可以通过Future获取返回值.但是Future接口调用get()方法取得结果时是阻塞的,如果调用Future对象的get ...

  9. Java并发编程核心方法与框架-CyclicBarrier的使用

    CyclicBarrier类似于CountDownLatch也是个计数器,不同的是CyclicBarrier数的是调用了CyclicBarrier.await()进入等待的线程数,当线程数达到了Cyc ...

随机推荐

  1. Java类加载器总结

    1.类的加载过程   JVM将类加载过程分为三个步骤:装载(Load),链接(Link)和初始化(Initialize)链接又分为三个步骤,如下图所示: 1) 装载:查找并加载类的二进制数据: 2)链 ...

  2. Linux基础3(文件权限)

    文件权限 1.普通权限 (登陆用户对文件或目录的读写执行的权限) 普通权限对管理员用户无效 文件和目录 都有4中类型的用户u 所有者 : 文件.目录的创建者g 所属组 : 文件.目录属于的用户组o 其 ...

  3. 【BZOJ-3832】Rally 拓扑序 + 线段树 (神思路题!)

    3832: [Poi2014]Rally Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 168  Solved:  ...

  4. Jquery打叉怎么办

    选中报错文件右键MyEclipse>Exclude From xxxx

  5. wpf数据绑定

    前段: <Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.c ...

  6. 订阅Linux内核的邮件列表

    1.发送订阅邮件 注意:一定不要使用像Foxmail这样的第三方邮件客户端,因为发送的邮件会转码,导致订阅不成功,推荐使用Gmail,直接登录进去发送. 发送邮件内容: 接收人:majordomo@v ...

  7. IIS提示“异常详细信息: System.Runtime.InteropServices.ExternalException: 无法执行程序”

    先来看错误提示: 无法执行程序.所执行的命令为 "C:/Windows/Microsoft.NET/Framework/v3.5/csc.exe" /noconfig /fullp ...

  8. PHP漏洞全解

    针对PHP的网站主要存在下面几种攻击方式: 1.命令注入(Command Injection) 2.eval注入(Eval Injection) 3.客户端脚本攻击(Script Insertion) ...

  9. dedecms /install/index.php.bak Installation File Not Deleted && Executed Via Apache Analytic Vul

    catalog . 漏洞描述 . 漏洞触发条件 . 漏洞影响范围 . 漏洞代码分析 . 防御方法 . 攻防思考 1. 漏洞描述 概括梳理一下这个漏洞的成因 . dedecms默认情况下安装完成之后,i ...

  10. [iOS 视频流开发-获得视频帧处理]

    调用视频流所使用框架:<Foundation/Foundation.h> 必须定义的参数: 1.AVCaptureDevice(捕获设备:前置.后置摄像头等) 2.AVCaptureInp ...