多线程-定时器、线程池

    • 定时器
      • 标准库的使用
    • 线程池使用
    • 线程数目确定

定时器

到一定时间就执行一个准备好的代码/方法。注册一个任务;任务会在指定时间进行执行。

标准库的使用

定时器:指定一个时间去执行一个任务,让程序去代替人工准时操作。

import java.util.Timer;
import java.util.TimerTask;

public class test18 {//标准库定时器的使用
    public static void main(String[] args) {
        System.out.println("任务启动前");
        Timer timer=new Timer();//有很多方法;参数。可以注册多个任务。也得看官方文档
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("任务启动后");
            }
        }, 3000);

        }

    }

线程池使用

并发量的提升我们会发现;线程的创建也会消耗不少资源;使用我们使用线程池降低线程的创建和销毁开销。因为线程池是事先就将线程创建好放入"线程池"中,后面需要的时候,直接从池子中取。这样就省去线程的创建和销毁开销;省一些CPU。

先看一下标准库的线程池怎么使用:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

// 使用一下标准库的线程池
public class ThreadDemo26 {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 1000; i++) {
            int n = i;
            pool.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("hello " + n);
                }
            });
        }
    }
}

ExecutorService pool = Executors.newFixedThreadPool(10);相当于new操作;这个操作很奇葩;用某个类的静态方法直接构造出一个对象来(相当于把new操作隐藏到方法后面)
工厂模式:上述的这种设计模式;用普通方法代替构造方法创建对象;但是有坑;如果创建多种对象;构造不同情况对象;多个构造方法得通过重载方式创建
submit方法:给线程池提交任务;线程池的线程都是前台线程;会阻止进程结束。定时器也是如此

有个问题:
多线程-定时器、线程池_第1张图片

lanbda表达式;这里的run方法属于Runnable;这个方法的执行时机是在未来的某个节点;后续线程池队列中;排到他就让对应的线程去执行。这个for循环的i是主线程的局部变量;主线程执行完就销毁了;run任务还没在线程池排到队;i就已经销毁。

变量捕获:内部类(Runnable的匿名内部类)捕获了外部方法中的局部变量n。
匿名内部类(包括Lambda表达式)可以访问它们周围方法的局部变量,n是一个局部变量,但它是final的,因为它在for循环内部不会被修改。
jdk1.8之前只能捕获final;而1.8后无需显式声明它们为final;只要代码没修改这个变量就可以捕获。
n是在每次迭代中都创建了一个新的变量实例,而i是在不同迭代中都指向相同的变量实例。所以i是没法捕获。

上述线程池的使用;就是一个工厂类;包装ThreadPooIExecutor实现的;让我们使用更方便。
多线程-定时器、线程池_第2张图片
ThreadPoolExecutor提供了更多的可选参数,可以进一步细化线程池行为的设定;后续再详细介绍;以及自定义的定时器、线程池的实现。

线程数目确定

1:CPU每个线程要执行的任务都是狂转CPU(进行一系列算术运算)此时线程池线程数多也不应该超过 CPU 核数
2:IO密集型每个线程干的工作就是等待 0(读写硬盘,读写网卡,等待用户输入…)不吃 CPU此时这样的线程处于阻塞状态不参与 CPU 调度;你就可以设置多一点
实际中:实践出真知;通过测试/实验的方式;看看哪个效果最好

你可能感兴趣的:(多线程,java,多线程)