java线程与线程池

线程

创建线程的三种方式

在这里插入图片描述

继承Thread类

在这里插入图片描述

实现Runnable接口

在这里插入图片描述

实现Callable接口

在这里插入图片描述

线程状态

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

线程方法

在这里插入图片描述

停止线程

在这里插入图片描述

线程休眠----sleep

在这里插入图片描述

线程礼让----yield

在这里插入图片描述
两个线程t1、t2,t1线程调用yield方法,t1线程进入就绪状态,等t2线程运行结束后再运行t1线程

线程强制执行----jion

在这里插入图片描述

线程的优先级

在这里插入图片描述

线程池

什么是线程池

在这里插入图片描述

为什么使用线程池

在这里插入图片描述
在这里插入图片描述

使用场景

在这里插入图片描述
在这里插入图片描述

线程池参数介绍

在这里插入图片描述

  • corePoolSize: 核心线程数量,当有一个任务提交到线程池的时候,如果当前线程池的线程数量没有达到核心线程数量,则创建线程来执行任务
  • maximunPoolSize: 最大线程数量,当有一个任务提交到线程池的时候,如果当前线程池的线程数量达到了核心线程的数量,并且任务队列也已经满了,则再在满足线程池最大线程数量的前提下,创建线程执行该任务,如果任务队列没有满,则该任务进入任务队列等该
  • keepAliveTime: 空闲线程的存活时间,当一个线程没有执行任务时(闲置时),能够存活的时间是多少,如果超过存活时间,则会被线程池回收
  • unit:空闲线程的存活时间的单位
  • workQueue:任务队列,当线程的数量达到线程池的核心线程数量,这个时候再有任务提交到线程池的时候,就会把这些任务加到任务队列里,如果任务队列也满了但线程数量没有达到最大线程数量,则会创建新的线程来执行任务
  • threadFactory:线程工厂,创建线程的工厂,允许我们自己参与创建线程的过程
  • handler:拒绝策略,当线程数量达到核心线程数量和最大线程数量,并且任务队列也存满了,线程池处于饱和状态,如果这个时候,还有任务提交到线程池,这个时候采取拒绝策略,是将这些任务丢弃还是让这些任务等待
    在这里插入图片描述

线程池工作流程介绍

在这里插入图片描述

参数设计分析

在这里插入图片描述
在这里插入图片描述

自定义线程池例子

创建任务类

package thread;

/**
 * 创建任务类,实现Runnable接口
 * 包含任务编号,每个任务执行时间为0.2秒
 */
public class MyTask implements Runnable{
    // 任务编号
    private int id;

    // 由于run方法是冲写接口中的方法,因此id这个属性初始化可以利用构造方法来完成
    public MyTask(int id) {
        this.id = id;
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println("线程 " + name + " 即将执行任务 " + id);
        // 为了模拟任务执行的时间,将线程休眠
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("线程 " + name + " 完成了任务 " + id);
    }

    @Override
    public String toString() {
        return "MyTask{" +
                "id=" + id +
                '}';
    }
}

创建线程类

package thread;

import java.util.List;

/**
 * 编写一个线程类,需要继承Thread类
 * 设计一个属性,用于保存线程的名字
 * 设计一个集合,用于保存所有的任务
 */
public class MyWorker extends Thread{
    // 保存线程的名字
    private String name;

    // 保存所有的任务
    private List<Runnable> tasks;

    // 使用构造方法完成属性的初始化


    public MyWorker(String name, List<Runnable> tasks) {
        super(name);
        this.tasks = tasks;
    }

    @Override
    public void run() {
        // 判断集合中是否还有任务,如果有,继续执行任务
        while (tasks.size() > 0) {
            Runnable r = tasks.remove(0);
            r.run();
        }
    }
}

创建线程池类

package thread;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

/**
 * 这是自定义的线程池类
 * 成员变量:
 * 1. 任务队列  集合  需要控制线程安全
 * 2. 当前线程数量
 * 3. 核心线程数
 * 4. 最大线程数
 * 5. 任务队列的长度
 *
 * 成员方法:
 * 1. 提交任务,将任务添加到集合中,需要判断任务是否超出了任务长度
 * 2. 执行任务,判断当前线程的数量,决定创建核心线程还是非核心线程
 */
public class MyThreadPool {
    // 1. 任务队列  Collections.synchronizedList() 宝成创建出来的集合线程是安全的
    private List<Runnable> tasks = Collections.synchronizedList(new LinkedList<>());

    // 当前线程数量
    private int num;

    // 核心线程数量
    private int corePoolSize;

    // 最大线程数量
    private int maxSize;

    // 任务队列的长度
    private int workSize;

    public MyThreadPool(int corePoolSize, int maxSize, int workSize) {
        this.corePoolSize = corePoolSize;
        this.maxSize = maxSize;
        this.workSize = workSize;
    }

    // 提交任务
    public void submit(Runnable r) {
        // 判断当前集合中任务的数量,是否超出了最大任务数量
        if (tasks.size() >= workSize) {
            System.out.println("任务:" + r + " 被丢弃了......");
        } else {
            // 将任务添加到任务队列
            tasks.add(r);
            // 执行任务
            execTask(r);
        }
    }

    // 执行任务
    private void execTask(Runnable r) {
        // 判断当前线程池中的线程数量,是否超出了核心线程
        if (num < corePoolSize) {
            new MyWorker("核心线程:" + num, tasks).start();
            num ++;
        } else if (num < maxSize) {
            new MyWorker("非核心线程:" + num, tasks).start();
            num ++;
        } else {
            System.out.println("任务 " + r + "被缓存了......");
        }
    }
}

测试类

package thread;

/**
 * 测试类:
 * 1. 创建线程池类对象
 * 2. 提交多个任务
 */
public class MyTest {
    public static void main(String[] args) {
        // 创建线程池对象
        MyThreadPool pool  = new MyThreadPool(2, 4, 20);
        // 提交任务
        for (int i = 0; i < 30; i++) {
            // 创建任务对象,提交给线程池
            MyTask my = new MyTask(i);
            pool.submit(my);
        }
    }
}

ExecutorService

在这里插入图片描述
在这里插入图片描述

newCachedThreadPool

package newCachedThreadPool;

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

/**
 * 联系Executor,获取ExecutorService,然后调用方法,提交任务
 */
public class MyTest01 {
    public static void main(String[] args) {
//        test1();
        test2();
    }

    // 练习newCachedThreadPool方法
    private static void test1() {
        // 1. 使用工厂类获取线程池对象
        ExecutorService es = Executors.newCachedThreadPool();
        // 2. 提交任务
        for (int i = 0; i < 10; i++) {
            es.submit(new MyRunnable(i));
        }
    }

    // 练习newCachedThreadPool重载方法
    private static void test2() {
        // 1. 使用工厂类获取线程池对象
        ExecutorService es = Executors.newCachedThreadPool(new ThreadFactory() {
            int n = 1;
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r, "自定义线程名称 " + n++);
            }
        });
        // 2. 提交任务
        for (int i = 0; i < 10; i++) {
            es.submit(new MyRunnable(i));
        }
    }
}

/**
 * 任务类
 * 包含一个任务编号
 * 在任务中打印出是哪一个线程正在执行任务
 */
class MyRunnable implements Runnable {
    // 任务编号
    private int id;

    public MyRunnable(int id) {
        this.id = id;
    }

    @Override
    public void run() {
        // 获取线程的名称,打印一句话
        String name = Thread.currentThread().getName();
        System.out.println(name + " 执行了任务....." + id);
    }
}

newFixedThreadPool

package newFixedThreadPool;

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

public class Test01 {
    public static void main(String[] args) {
//        test1();
        test2();
    }

    // 练习newFixedThreadPool方法
    private static void test1() {
        // 使用工厂类获取线程池对象
        ExecutorService es = Executors.newFixedThreadPool(3);
        // 提交任务
        for (int i = 0; i < 10; i++) {
            es.submit(new MyRunnable(i));
        }
    }

    // 练习newFixedThreadPool重载方法
    private static void test2() {
        // 使用工厂类获取线程池对象
        ExecutorService es = Executors.newFixedThreadPool(3, new ThreadFactory() {
            int i = 1;
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r, "自定义线程名称 " + i++);
            }
        });
        // 提交任务
        for (int i = 0; i < 10; i++) {
            es.submit(new MyRunnable(i));
        }
    }
}

// 这是一个任务类,包含任务编号
class MyRunnable implements Runnable {
    private int id;

    public MyRunnable(int id) {
        this.id = id;
    }

    @Override
    public void run() {
        // 获取线程的名称,打印一句话
        String name = Thread.currentThread().getName();
        System.out.println(name + " 执行了任务....." + id);
    }
}

newSingleThreadExecutor

package newSingleThreadExector;

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

public class Test {
    public static void main(String[] args) {
//        test1();
        test2();
    }

    // 练习newSingleThreadExecutor方法
    private static void test1() {
        // 使用工厂类获取线程池
        ExecutorService es = Executors.newSingleThreadExecutor();
        // 提交任务
        for (int i = 0; i < 10; i++) {
            es.submit(new MyRunnable(i));
        }
    }

    // 练习newSingleThreadExecutor重载方法
    private static void test2() {
        // 使用工厂类获取线程池
        ExecutorService es = Executors.newSingleThreadExecutor(new ThreadFactory() {
            int i = 1;
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r, "自定义线程 " + i ++);
            }
        });
        // 提交任务
        for (int i = 0; i < 10; i++) {
            es.submit(new MyRunnable(i));
        }
    }
}

/**
 * 任务类,包含任务编号
 */
class MyRunnable implements Runnable {
    private int id;

    public MyRunnable(int id) {
        this.id = id;
    }

    @Override
    public void run() {
        // 获取线程的名称,打印一句话
        String name = Thread.currentThread().getName();
        System.out.println(name + " 执行了任务....." + id);
    }
}

ExecutorService中的shutdown和shutdownNow方法

package threadPool;

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

/**
 * 练习Executor获取ExecutorService,测试关闭线程池的方法
 */
public class Test01 {
    public static void main(String[] args) {
        // 使用工厂类获取线程池
        ExecutorService es = Executors.newSingleThreadExecutor();
        // 提交任务
        for (int i = 0; i < 10; i++) {
            es.submit(new MyRunnable(i));
        }

        // 关闭线程池,仅仅是不再接收新的任务,以前的任务还是会继续执行
        // es.shutdown();
        // es.submit(new MyRunnable(55));  // 不允许再提交新的任务

        // 立刻关闭线程池,如果线程池中还有缓存的任务,没有执行,则取消执行,并返回这些任务
        List<Runnable> list = es.shutdownNow();
        list.forEach(i -> System.out.println(i));
    }
}

/**
 * 任务类,包含任务编号
 */
class MyRunnable implements Runnable {
    private int id;

    public MyRunnable(int id) {
        this.id = id;
    }

    @Override
    public void run() {
        // 获取线程的名称,打印一句话
        String name = Thread.currentThread().getName();
        System.out.println(name + " 执行了任务....." + id);
    }

    @Override
    public String toString() {
        return "MyRunnable{" +
                "id=" + id +
                '}';
    }
}

ScheduledExecutorService

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值