鱼C论坛

 找回密码
 立即注册
查看: 2604|回复: 1

[学习笔记] Java032-线程池、定时器

[复制链接]
发表于 2019-1-13 22:31:34 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 moc 于 2019-1-13 22:53 编辑

1、线程组
把多个线程组合到一起,对一批线程进行分类管理,Java允许程序直接对线程组进行控制。
  1. // 线程子类
  2. public class MyRunnable implements Runnable {
  3.         @Override
  4.         public void run() {
  5.                 for (int x = 0; x < 100; x++) {
  6.                         System.out.println(Thread.currentThread().getName() + ":" + x);
  7.                 }
  8.         }
  9. }
  10. // 测试类
  11. public class ThreadGroupDemo {
  12.         public static void main(String[] args) {       
  13.                 MyRunnable my = new MyRunnable();
  14.                 Thread t1 = new Thread(my, "小明");
  15.                 Thread t2 = new Thread(my, "小华");

  16.                 // public final ThreadGroup getThreadGroup()  查看线程属于哪个组,获得线程组
  17.                 ThreadGroup tg1 = t1.getThreadGroup();
  18.                 ThreadGroup tg2 = t2.getThreadGroup();
  19.                
  20.                 // public final String getName()   查看线程组的名称
  21.                 String name1 = tg1.getName();
  22.                 String name2 = tg2.getName();
  23.                 System.out.println(name1);
  24.                 System.out.println(name2);
  25.                 System.out.println(Thread.currentThread().getThreadGroup().getName());
  26.                 // 通过结果知道:线程默认情况下属于main线程组
  27.                 // 通过下面的测试,你应该能够看到,默任情况下,所有的线程都属于同一个组
  28.                
  29.                 // ThreadGroup(String name)   创建新的分组  
  30.                 ThreadGroup tg = new ThreadGroup("这是一个新的组");
  31.                
  32.                 // Thread(ThreadGroup group, Runnable target, String name)
  33.                 Thread t3 = new Thread(tg, my, "小王");
  34.                 Thread t4 = new Thread(tg, my, "小刘");
  35.                
  36.                 System.out.println(t1.getThreadGroup().getName());
  37.                 System.out.println(t2.getThreadGroup().getName());
  38.                
  39.                 //通过组名称设置后台线程,表示该组的线程都是后台线程
  40.                 tg.setDaemon(true);
  41.         }
  42. }
复制代码
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方法;
        ④ 结束线程池。
线程求和案例:
  1. // Callable 接口实现类;
  2. public class MyCallable implements Callable<Integer> {
  3.         private int number;
  4.         public MyCallable(int number) {
  5.                 this.number = number;
  6.         }

  7.         @Override
  8.         public Integer call() throws Exception {
  9.                 int sum = 0;
  10.                 for (int x = 1; x <= number; x++) {
  11.                         sum += x;
  12.                 }
  13.                 return sum;
  14.         }
  15. }
  16. // 测试类
  17. ublic class CallableDemo {
  18.         public static void main(String[] args) throws InterruptedException, ExecutionException {
  19.                 // 创建线程池对象
  20.                 ExecutorService pool = Executors.newFixedThreadPool(2);

  21.                 // 可以执行Runnable对象或者Callable对象代表的线程
  22.                 Future<Integer> f1 = pool.submit(new MyCallable(100));
  23.                 Future<Integer> f2 = pool.submit(new MyCallable(200));

  24.                 // V get()
  25.                 Integer i1 = f1.get();
  26.                 Integer i2 = f2.get();

  27.                 System.out.println(i1);
  28.                 System.out.println(i2);

  29.                 // 结束
  30.                 pool.shutdown();
  31.         }
  32. }
复制代码
4、匿名内部类实现多线程
这种方式用于只执行一次的复杂任务。
本质:是该类或者接口的子类对象。
  1. public class ThreadDemo {
  2.         public static void main(String[] args) {
  3.                 // 继承Thread类来实现多线程
  4.                 new Thread() {
  5.                         public void run() {
  6.                                 for (int x = 0; x < 10; x++) {
  7.                                         System.out.println(Thread.currentThread().getName() + ":" + x);
  8.                                 }
  9.                         }
  10.                 }.start();

  11.                 // 实现Runnable接口来实现多线程
  12.                 new Thread(new Runnable() {
  13.                         @Override
  14.                         public void run() {
  15.                                 for (int x = 0; x < 10; x++) {
  16.                                         System.out.println(Thread.currentThread().getName() + ":" + x);
  17.                                 }
  18.                         }
  19.                 }) {
  20.                 }.start();

  21.                 // 都写啦,只会执行继承来的,即world那一个
  22.                 new Thread(new Runnable() {
  23.                         @Override
  24.                         public void run() {
  25.                                 for (int x = 0; x < 10; x++) {
  26.                                         System.out.println("hello" + ":" + x);
  27.                                 }
  28.                         }
  29.                 } {
  30.                         public void run() {
  31.                                 for (int x = 0; x < 100; x++) {
  32.                                         System.out.println("world" + ":" + x);
  33.                                 }
  34.                         }
  35.                 }.start();
  36.         }
  37. }
复制代码

5、定时器
让我们在指定的时间做某件事情或固定时间间隔重复性做某件事情。
包: java.util.Timer、java.util.TimerTask
方法:
Timer: 定时
Timer([String name] [,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() ---------->  取消此计时器任务。
  1. // 定时器任务
  2. class MyTask extends TimerTask {
  3.         @Override
  4.         public void run() {
  5.                 System.out.println("beng,爆炸了");
  6.         }
  7. }
  8. // 测试类
  9. public class TimerDemo2 {
  10.         public static void main(String[] args) {
  11.                 // 创建定时器对象
  12.                 Timer t = new Timer();
  13.                 // 3秒后执行爆炸任务第一次,每隔2秒再继续炸
  14.                 t.schedule(new MyTask2(), 3000, 2000);
  15.         }
  16. }
复制代码

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2019-1-17 11:25:24 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-19 22:25

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表