java threadpool修改线程数 java threadexecutor
转载
在JDK1.5之前,如果需要使用线程池,需要自己动手写代码实现,这对于初学者来说,不是一件容易的事。JDK1.5提供了Executor类,用户通过它可得到各种类型的线程池。
Executor提供的线程池,可以分为:固定尺寸的线程池、可变尺寸的线程池。
Executor.java提供部分接口
public static ExecutorService newFixedThreadPool(int nThreads)
| 创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。
|
public static ExecutorService newSingleThreadExecutor()
| 创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程。
|
public static ExecutorService newCachedThreadPool()
| 创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。
|
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
| 创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
|
public static ScheduledExecutorService newSingleThreadScheduledExecutor()
| 创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程。
|
public static ExecutorService newFixedThreadPool(int n),线程池中有n个线程,如果实际线程数m,m>n,则先加入的前n个线程,先执行,处于执行状态,后加入的m-n个线程,处于阻塞状态,直到有某个线程执行完了,则处于阻塞状态的线程中的其中一个启动。也就是说最多同时n个线程处于执行状态。 package thread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolTest {
public static void main(String[] args) {
ExecutorService executorService=Executors.newFixedThreadPool(3);
MyThread a=new MyThread("A");
MyThread b=new MyThread("B");
MyThread c=new MyThread("C");
MyThread d=new MyThread("D");
executorService.execute(a);
executorService.execute(b);
executorService.execute(c);
executorService.execute(d);
executorService.shutdown();
}
static class MyThread implements Runnable{
private String name;
public MyThread(String name){
this.name=name;
}
@Override
public void run(){
for(int i=1;i<=5;i++){
System.out.println(this.name+"第"+i+"次运行.........");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
运行结果 B第1次运行.........
C第1次运行.........
A第1次运行.........
B第2次运行.........
C第2次运行.........
A第2次运行.........
B第3次运行.........
C第3次运行.........
A第3次运行.........
B第4次运行.........
C第4次运行.........
A第4次运行.........
B第5次运行.........
C第5次运行.........
A第5次运行.........
D第1次运行.........
D第2次运行.........
D第3次运行.........
D第4次运行.........
D第5次运行.........
ABC同时启动,所以打印顺序是混乱的;最后有空闲线程资源执行D时,只有它在执行,所以看上去有序。
|
public static ExecutorService newSingleThreadExecutor()线程池中的线程数为1,如果实际线程数大于1时,则按照加入的顺序按顺序执行。所以如果开发中遇到多个线程一个个执行(前一个执行完后,后一个才能执行)的话,可以使用这种方式就可以避免使用join()方法,一个个控制了。 将上面程序获得线程池的语句修改一下。
// ExecutorService executorService=Executors.newFixedThreadPool(3);
ExecutorService executorService=Executors.newSingleThreadExecutor();
运行结果 A第1次运行.........
A第2次运行.........
A第3次运行.........
A第4次运行.........
A第5次运行.........
B第1次运行.........
B第2次运行.........
B第3次运行.........
B第4次运行.........
B第5次运行.........
C第1次运行.........
C第2次运行.........
C第3次运行.........
C第4次运行.........
C第5次运行.........
D第1次运行.........
D第2次运行.........
D第3次运行.........
D第4次运行.........
D第5次运行.........
运行结果是有序的。 |
public static ExecutorService newCachedThreadPool()动态创建线程数,如果新加入一个线程任务,当前线程池中没有空闲的线程,则新创建一个线程用来执行新任务;如果有空闲线程,则使用空闲线程。一个线程的任务执行完后,线程状态成为空闲状态,线程不会立即销毁,60秒后,如果没有新任务进来,则空闲线程(空闲时间已达到60s)就销毁. 将上面程序获取线程池的语句修改下。
// ExecutorService executorService=Executors.newFixedThreadPool(3);
// ExecutorService executorService=Executors.newSingleThreadExecutor();
ExecutorService executorService=Executors.newCachedThreadPool();
运行结果B 第1次运行.........
D第1次运行.........
A第1次运行.........
C第1次运行.........
B第2次运行.........
D第2次运行.........
A第2次运行.........
C第2次运行.........
B第3次运行.........
D第3次运行.........
A第3次运行.........
C第3次运行.........
D第4次运行.........
B第4次运行.........
A第4次运行.........
C第4次运行.........
B第5次运行.........
D第5次运行.........
A第5次运行.........
C第5次运行.........
ABCD的运行是混乱的。
|
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize),看方法名就知道,该线程池可以执行定时任务。 package thread;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ThreadPoolTest {
public static void main(String[] args) {
ScheduledExecutorService executorService=Executors.newScheduledThreadPool(3);
MyThread a=new MyThread("A");
MyThread b=new MyThread("B");
MyThread c=new MyThread("C");
MyThread d=new MyThread("D");
executorService.schedule(a, 1000, TimeUnit.MILLISECONDS);//1000毫秒后执行
executorService.schedule(b, 500, TimeUnit.MILLISECONDS);//500ms后执行
executorService.schedule(c, 1, TimeUnit.SECONDS);//1s后执行
executorService.schedule(d, 1, TimeUnit.SECONDS);
executorService.shutdown();
}
static class MyThread implements Runnable{
private String name;
public MyThread(String name){
this.name=name;
}
@Override
public void run(){
for(int i=1;i<=3;i++)
System.out.println(name+"在执行第"+i+"次....."+new SimpleDateFormat("hh:mm:ss").format(new Date()));
}
}
}
运行结果 B在执行第1次.....08:20:16
B在执行第2次.....08:20:16
B在执行第3次.....08:20:16
A在执行第1次.....08:20:17
A在执行第2次.....08:20:17
A在执行第3次.....08:20:17
C在执行第1次.....08:20:17
C在执行第2次.....08:20:17
C在执行第3次.....08:20:17
D在执行第1次.....08:20:17
D在执行第2次.....08:20:17
D在执行第3次.....08:20:17
至于public static ScheduledExecutorService newSingleThreadScheduledExecutor(),读者可以将上面程序修改下就OK了。 运行结果 B在执行第1次.....08:25:08
B在执行第2次.....08:25:08
B在执行第3次.....08:25:08
A在执行第1次.....08:25:09
A在执行第2次.....08:25:09
A在执行第3次.....08:25:09
C在执行第1次.....08:25:09
C在执行第2次.....08:25:09
C在执行第3次.....08:25:09
D在执行第1次.....08:25:09
D在执行第2次.....08:25:09
D在执行第3次.....08:25:09
|
本文章为转载内容,我们尊重原作者对文章享有的著作权。如有内容错误或侵权问题,欢迎原作者联系我们进行内容更正或删除文章。