常⽤的线程池(4种)及应⽤实例本⽂基础语⾔java。
1、传统新建线程的两种⽅式:
(1)new Thread 对象继承Thread的时候。
public class ThreadTest2 extends Thread {
private int threadCnt = 10;
@Override
public void run() {
while (true) {
if (threadCnt > 0) {
System.out.println(Thread.currentThread().getName() + " 剩余个数 " + threadCnt);
threadCnt--;
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
break;
}
}
}
public static void main(String[] args) {
new ThreadTest2().start();
new ThreadTest2().start();
}
}
(2)、对象在实现runnable ⽅法的时候
public class RunnalbleTest2 implements Runnable {
private int threadCnt = 10;
@Override
public void run() {
while (true) {
if (threadCnt > 0) {
System.out.println(Thread.currentThread().getName() + " 剩余个数 " + threadCnt);
threadCnt--;
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
break;
}
}
}
public static void main(String[] args) {
RunnalbleTest2 runnalbleTest2 = new RunnalbleTest2();
new Thread(runnalbleTest2).start();
new Thread(runnalbleTest2).start();
new Thread(runnalbleTest2).start();
new Thread(runnalbleTest2).start();
}
}
new Thread在并发编程中有很多劣势:
a.每次new Thread新建对象性能差。
b. 线程缺乏统⼀管理,可能⽆限制新建线程,相互之间竞争,及可能占⽤过多系统资源导致死机或oom。
c. 缺乏更多功能,如定时执⾏、定期执⾏、线程中断。
java 四种常⽤的线程池
要配置⼀个线程池是⽐较复杂的,尤其是对于线程池的原理不是很清楚的情况下,很有可能配置的线程池不是较优的,因此在Executors类⾥⾯提供了⼀些静态⼯⼚,⽣成⼀些常⽤的线程池。
下⾯是Java提供常⽤四种线程池。
newCachedThreadPool创建⼀个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若⽆可回收,则新建线程。newFixedThreadPool 创建⼀个定长线程池,可控制线程最⼤并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建⼀个定长线程池,⽀持定时及周期性任务执⾏。
newSingleThreadExecutor 创建⼀个单线程化的线程池,它只会⽤唯⼀的⼯作线程来执⾏任务,保证所有任务按照指定顺序(FIFO, LIFO,优先级)执⾏。
(1)newCachedThreadPool:
可以缓冲的线程池,如果线程池的长度超过处理的需要。可以灵活的回收空闲线程,如果没有可以回收的线程,则需要新建线程。具体的实现⽅式为:
ExecutorService cachedThreadPool = wCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int index = i;
try {
Thread.sleep(index * 1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
@Override
public void run() {
System.out.println(index);
}
});
}
另⼀种实现⽅式为:
utors;
import urrent.Executors;
import urrent.ExecutorService;
/
**
*/
public class Test {
public static void main(String[] args) {
// 创建⼀个可重⽤固定线程数的线程池
ExecutorService pool = wCachedThreadPool();
// 创建线程
Thread t1 = new MyThread();
Thread t2 = new MyThread();
Thread t3 = new MyThread();
Thread t4 = new MyThread();
Thread t5 = new MyThread();
// 将线程放⼊池中进⾏执⾏
// 关闭线程池
pool.shutdown();
}
java线程池创建的四种}
class MyThread extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "正在执⾏。。。");
}
}
注意:此线程池特点为创建⼀个可缓存的线程池,如果线程池的⼤⼩超过了处理任务需要的的线程时,(此时说明线程池中的线程⼤于任务所需的线程),线程池会启动回收机制,回收策略为将60秒内不执⾏任务的线程回收。⽽当任务数量增加时,此时线程池⼜可以智能的添加新线程来处理任务,此线程不会对线程池的线程数做⼤⼩限制,线程池可以创建线程的多少依赖于操作系统(或者说JVM)能够创建的最⼤线程⼤⼩。
(2)、newFixedThreadPool:
创建⼀个定长线程池,可以控制线程的最⼤并发数量。超出的线程会加⼊到队列中进⾏等待。开发的实例代码为:
(创建时可以指定线程池的长度如下3)
ExecutorService fixedThreadPool = wFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
final int index = i;
@Override
public void run() {
try {
System.out.println(index);
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
另⼀种参考如上完成
注意:创建固定长度的线程池的特点为,每次提交⼀个任务都回创建⼀个线程。直到线程数量达到线程池的最⼤长度,线程池的⼤⼩⼀旦到达最⼤,线程池的线程的个数就不会减少。如果某个线程因为执⾏异常⽽结束,那么线程池会补充⼀个新线程。定长线程池的⼤⼩最好根据系统资源进⾏限制 。如Runtime().availableProcessors()、可参考PreloadDataCache。 todo
(3)、newScheduledThreadPool:
此线程池是上⾯的变形,也是创建⼀个定长线程池,并⽀持定时及周期性的任务执⾏,先吃执⾏的代码如下。(延迟三秒执⾏)
ScheduledExecutorService scheduledThreadPool = wScheduledThreadPool(5);
scheduledThreadPool.schedule(new Runnable() {
@Override
public void run() {
System.out.println("delay 3 seconds");
}
}, 3, TimeUnit.SECONDS);
定期执⾏⽰例代码如下()延迟1秒后每3秒执⾏⼀次
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("delay 1 seconds, and excute every 3 seconds");
}
}, 1, 3, TimeUnit.SECONDS);
⽅式⼆:
public class TestScheduledThreadPoolExecutor {
public static void main(String[] args) {
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
exec.scheduleAtFixedRate(new Runnable() {//每隔⼀段时间就触发异常
@Override
publicvoid run() {
//throw new RuntimeException();
System.out.println("================");
}
}, 1000, 5000, TimeUnit.MILLISECONDS);
exec.scheduleAtFixedRate(new Runnable() {//每隔⼀段时间打印系统时间,证明两者是互不影响的
@Override
publicvoid run() {
System.out.println(System.nanoTime());
}
}, 1000, 2000, TimeUnit.MILLISECONDS);
}
}
注意:创建⼀个⼤⼩⽆限的线程池。此线程池⽀持定时以及周期性执⾏任务的需求。此线程池功能加上了定时调度的功能很多时候⽐Timer 定时调度功能更安全、强⼤
(4)、newSingleThreadExecutor:
创建⼀个单⼀的线程化的线程池,它只会⽤唯⼀的⼯作线程来执⾏任务。保证任务按照指定顺序(FiFO、LIFO、优先级)执⾏,事例代码:
ExecutorService singleThreadExecutor = wSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int index = i;
@Override
public void run() {
try {
System.out.println(index);
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论