Java032-线程池、定时器
本帖最后由 moc 于 2019-1-13 22:53 编辑1、线程组
把多个线程组合到一起,对一批线程进行分类管理,Java允许程序直接对线程组进行控制。
// 线程子类
public class MyRunnable implements Runnable {
@Override
public void run() {
for (int x = 0; x < 100; x++) {
System.out.println(Thread.currentThread().getName() + ":" + x);
}
}
}
// 测试类
public class ThreadGroupDemo {
public static void main(String[] args) {
MyRunnable my = new MyRunnable();
Thread t1 = new Thread(my, "小明");
Thread t2 = new Thread(my, "小华");
// public final ThreadGroup getThreadGroup()查看线程属于哪个组,获得线程组
ThreadGroup tg1 = t1.getThreadGroup();
ThreadGroup tg2 = t2.getThreadGroup();
// public final String getName() 查看线程组的名称
String name1 = tg1.getName();
String name2 = tg2.getName();
System.out.println(name1);
System.out.println(name2);
System.out.println(Thread.currentThread().getThreadGroup().getName());
// 通过结果知道:线程默认情况下属于main线程组
// 通过下面的测试,你应该能够看到,默任情况下,所有的线程都属于同一个组
// ThreadGroup(String name) 创建新的分组
ThreadGroup tg = new ThreadGroup("这是一个新的组");
// Thread(ThreadGroup group, Runnable target, String name)
Thread t3 = new Thread(tg, my, "小王");
Thread t4 = new Thread(tg, my, "小刘");
System.out.println(t1.getThreadGroup().getName());
System.out.println(t2.getThreadGroup().getName());
//通过组名称设置后台线程,表示该组的线程都是后台线程
tg.setDaemon(true);
}
}2、线程池简介
1. 线程池的优点
① 线程是稀缺资源,使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以重复使用。
③ 可以根据系统的承受能力,调整线程池中工作线程的数量,防止因为消耗过多内存导致服务器崩溃。
2. 线程池的实现原理
提交一个任务到线程池中,线程池的处理流程如下:
① 当提交一个任务时,线程池创建一个新线程并执行任务,直到当前线程数等于核心线程数(corePoolSize),等于后再有任务进入②;
② 线程池判断工作队列是否已满,如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果工作队列满了,则进入③;
③ 判断线程池里的线程是否都处于工作状态,如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务。
四种线程池:
public static ExecutorService newCachedThreadPool() --------------------------------------> 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
public static ExecutorService newFixedThreadPool(int nThreads)-------------------------> 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) ----> 创建一个定长线程池,支持定时及周期性任务执行。
public static ExecutorService newSingleThreadExecutor() -----------------------------------> 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
3、线程实现方式3:实现Callable接口
步骤:
① 创建一个线程池对象,控制要创建几个线程对象,线程池可以执行Runnable对象或者Callable对象代表的线程;
② 实现Callable 接口的类;
③ 调用如下方法即可 submit方法;
④ 结束线程池。
线程求和案例:
// Callable 接口实现类;
public class MyCallable implements Callable<Integer> {
private int number;
public MyCallable(int number) {
this.number = number;
}
@Override
public Integer call() throws Exception {
int sum = 0;
for (int x = 1; x <= number; x++) {
sum += x;
}
return sum;
}
}
// 测试类
ublic class CallableDemo {
public static void main(String[] args) throws InterruptedException, ExecutionException {
// 创建线程池对象
ExecutorService pool = Executors.newFixedThreadPool(2);
// 可以执行Runnable对象或者Callable对象代表的线程
Future<Integer> f1 = pool.submit(new MyCallable(100));
Future<Integer> f2 = pool.submit(new MyCallable(200));
// V get()
Integer i1 = f1.get();
Integer i2 = f2.get();
System.out.println(i1);
System.out.println(i2);
// 结束
pool.shutdown();
}
}4、匿名内部类实现多线程
这种方式用于只执行一次的复杂任务。
本质:是该类或者接口的子类对象。
public class ThreadDemo {
public static void main(String[] args) {
// 继承Thread类来实现多线程
new Thread() {
public void run() {
for (int x = 0; x < 10; x++) {
System.out.println(Thread.currentThread().getName() + ":" + x);
}
}
}.start();
// 实现Runnable接口来实现多线程
new Thread(new Runnable() {
@Override
public void run() {
for (int x = 0; x < 10; x++) {
System.out.println(Thread.currentThread().getName() + ":" + x);
}
}
}) {
}.start();
// 都写啦,只会执行继承来的,即world那一个
new Thread(new Runnable() {
@Override
public void run() {
for (int x = 0; x < 10; x++) {
System.out.println("hello" + ":" + x);
}
}
} {
public void run() {
for (int x = 0; x < 100; x++) {
System.out.println("world" + ":" + x);
}
}
}.start();
}
}
5、定时器
让我们在指定的时间做某件事情或固定时间间隔重复性做某件事情。
包: java.util.Timer、java.util.TimerTask
方法:
Timer: 定时
Timer( [,boolean isDaemon])------------------------------> 构造函数,创建一个计时器,【指定相关的线程的名称】,【指定作为守护线程运行】
public void schedule(TimerTask task, long delay) ------------------------>安排在指定延迟后执行指定的任务。
public void schedule(TimerTask task,long delay,long period) ---------->安排指定的任务从指定的延迟后开始进行重复的固定延迟执行。
public void cancel()----------------------------------------------------------->终止此计时器,丢弃所有当前已安排的任务。
public void schedule(TimerTask task, Date firstTime[,long period]) --->安排指定的任务在指定的时间【开始进行重复的固定】延迟执行。
TimerTask: 任务
public abstract void run()--------> 此计时器任务要执行的操作。
public boolean cancel() ---------->取消此计时器任务。
// 定时器任务
class MyTask extends TimerTask {
@Override
public void run() {
System.out.println("beng,爆炸了");
}
}
// 测试类
public class TimerDemo2 {
public static void main(String[] args) {
// 创建定时器对象
Timer t = new Timer();
// 3秒后执行爆炸任务第一次,每隔2秒再继续炸
t.schedule(new MyTask2(), 3000, 2000);
}
} {:10_249:}
页:
[1]