Java 进阶多线程(二)

简介: Java 进阶多线程



一、线程通信(了解)

概念

线程通信就是线程间相互发送数据,线程间共享一个资源即可实现线程通信

常见方式

通过共享一个数据的方式实现

根据共享数据的情况决定自己该怎么做,以及通知其他线程怎么做

场景

生产者与消费者模型:生产者线程负责生产数据,消费者线程负责消费生产者产生的数据

要求

生产者线程生产完数据后唤醒消费者,然后等待自己,消费者消费完该数据后唤醒生产者,然后等待自己

方法名 解释

void wait() 当前线程等待,直到另一个线程调用notify() 或 notifyAll()唤醒自己

void notify() 唤醒正在等待对象监视器(锁对象)的单个线程

void notifyAll() 唤醒正在等待对象监视器(锁对象)的所有线程

二、线程池(重点)

概述

可以复用线程的技术

1、获得线程池对象

用ExecutorService实现类ThreadPoolExecutor自创建一个线程池对象

用Executors(线程池的工具类)调用方法返回不同特点的线程池对象

public ThreadPoolExecutor(
            int corePoolSize,//核心线程数
            int maximumPoolSize,//最大线程数
            long keepAliveTime,//线程空闲时间
            TimeUnit unit,//时间单位
            BlockingQueue<Runnable> workQueue,//任务队列
            ThreadFactory threadFactory,//线程工厂
            RejectedExecutionHandler handler//拒绝策略
    )

参数名 解释

corePoolSize 指定线程池的线程数量(核心线程),不能小于0

maximumPoolSize 指定线程池可支持的最大线程数,最大数量 >= 核心线程数量

keepAliveTime 指定临时线程的最大存活时间 ,不能小于0

unit 指定存活时间的单位(秒、分、时、天)

workQueue 指定任务队列 ,不能为null

threadFactory 指定用哪个线程工厂创建线程,不能为null

handler 指定线程忙,任务满的时候,新任务来了怎么办,不能为null

TimeUnit.DAYS;               //天
TimeUnit.HOURS;             //小时
TimeUnit.MINUTES;           //分钟
TimeUnit.SECONDS;           //秒
TimeUnit.MILLISECONDS;      //毫秒
TimeUnit.MICROSECONDS;      //微妙
TimeUnit.NANOSECONDS;       //纳秒

2、线程池处理Runnable

ExecutorService方法 解释

void execute(Runnable command) 执行任务/命令,没有返回值,一般用来执行 Runnable 任务

Future submit(Callable task) 执行任务,返回未来任务对象获取线程结果,一般拿来执行 Callable 任务

void shutdown() 等任务执行完毕后关闭线程池

List shutdownNow() 立刻关闭,停止正在执行的任务,并返回队列中未执行的任务

4种策略 解释

ThreadPoolExecutor.AbortPolicy 丢弃任务并抛出RejectedExecutionException异常。是默认的策略

ThreadPoolExecutor.DiscardPolicy 丢弃任务,但是不抛出异常 这是不推荐的做法

ThreadPoolExecutor.DiscardOldestPolicy 抛弃队列中等待最久的任务 然后把当前任务加入队列中

ThreadPoolExecutor.CallerRunsPolicy 由主线程负责调用任务的run()方法从而绕过线程池直接执行

1)AbortPolicy实战

当运行任务数超过核心数时,会报RejectedExecutionException错误

bd22c9e1b9408cfb63aa789dfc1936e.png

import java.util.concurrent.*;
public class ThreadPoolExecutorTest implements Runnable {
    private String name;
    public ThreadPoolExecutorTest(String name) {
        this.name = name;
    }
    @Override
    public void run() {
        try {
            System.out.println("当前线程名: " + Thread.currentThread().getName() + ", 任务 " + name + " is running!");
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        //线程池
        ExecutorService pools = new ThreadPoolExecutor(
                1,
                1,
                1,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        ThreadPoolExecutorTest run = null;
        // 循环创建线程
        for (int i = 0; i < 5; i++) {
            run = new ThreadPoolExecutorTest("" + i);
            // 将任务添加到线程池中
            pools.execute(run);
        }
        //关闭线程池
        pools.shutdown();
    }
}

2)DiscardPolicy实战

af429dbd52d27ca4ec47c3b154f496b.png

import java.util.concurrent.*;
public class ThreadPoolExecutorTest implements Runnable {
    private String name;
    public ThreadPoolExecutorTest(String name) {
        this.name = name;
    }
    @Override
    public void run() {
        try {
            System.out.println("当前线程名: " + Thread.currentThread().getName() + ", 任务 " + name + " is running!");
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        //线程池
        ExecutorService pools = new ThreadPoolExecutor(
                1,
                1,
                1,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.DiscardPolicy());
        ThreadPoolExecutorTest run = null;
        // 循环创建线程
        for (int i = 0; i < 5; i++) {
            run = new ThreadPoolExecutorTest("" + i);
            // 将任务添加到线程池中
            pools.execute(run);
        }
        //关闭线程池
        pools.shutdown();
    }
}

3)DiscardOldestPolicy实战

74ee5dc70dd489d184251712057945b.png

import java.util.concurrent.*;
public class ThreadPoolExecutorTest implements Runnable {
    private String name;
    public ThreadPoolExecutorTest(String name) {
        this.name = name;
    }
    @Override
    public void run() {
        try {
            System.out.println("当前线程名: " + Thread.currentThread().getName() + ", 任务 " + name + " is running!");
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        //线程池
        ExecutorService pools = new ThreadPoolExecutor(
                1,
                1,
                1,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.DiscardOldestPolicy());
        ThreadPoolExecutorTest run = null;
        // 循环创建线程
        for (int i = 0; i < 5; i++) {
            run = new ThreadPoolExecutorTest("" + i);
            // 将任务添加到线程池中
            pools.execute(run);
        }
        //关闭线程池
        pools.shutdown();
    }
}

4)CallerRunsPolicy实战

616ec0ae584c0e3fc87d1353df51eb3.png

import java.util.concurrent.*;
public class ThreadPoolExecutorTest implements Runnable {
    private String name;
    public ThreadPoolExecutorTest(String name) {
        this.name = name;
    }
    @Override
    public void run() {
        try {
            System.out.println("当前线程名: " + Thread.currentThread().getName() + ", 任务 " + name + " is running!");
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        //线程池
        ExecutorService pools = new ThreadPoolExecutor(
                1,
                1,
                1,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.CallerRunsPolicy());
        ThreadPoolExecutorTest run = null;
        // 循环创建线程
        for (int i = 0; i < 5; i++) {
            run = new ThreadPoolExecutorTest("" + i);
            // 将任务添加到线程池中
            pools.execute(run);
        }
        //关闭线程池
        pools.shutdown();
    }
}

3、线程池处理Callable

ExecutorService方法 解释

void execute(Runnable command) 执行任务/命令,没有返回值,一般用来执行 Runnable 任务

Future submit(Callable task) 执行任务,返回未来任务对象获取线程结果,一般拿来执行 Callable 任务

void shutdown() 等任务执行完毕后关闭线程池

List shutdownNow() 立刻关闭,停止正在执行的任务,并返回队列中未执行的任务

c08e869345f27f49a1b5d4b6ace1418.png

import java.util.concurrent.Callable;
public class MyCallable implements Callable {
    private String name;
    public MyCallable(String name) {
        this.name = name;
    }
    @Override
    public Object call() throws Exception {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + name + " " + i);
        }
        return true;
    }
}
import java.util.concurrent.*;
public class ThreadPoolExecutorTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建线程池
        ExecutorService pools = Executors.newFixedThreadPool(3);
        MyCallable myCallable1 = new MyCallable(" hadoop");
        MyCallable myCallable2 = new MyCallable(" flink");
        MyCallable myCallable3 = new MyCallable(" spark");
        //提交执行
        Future<Boolean> sb1 = pools.submit(myCallable1);
        Future<Boolean> sb2 = pools.submit(myCallable2);
        Future<Boolean> sb3 = pools.submit(myCallable3);
        //获取结果
        boolean b1 = sb1.get();
        boolean b2 = sb2.get();
        boolean b3 = sb3.get();
        System.out.println(b1);
        System.out.println(b2);
        System.out.println(b3);
        // 关闭线程池,如不关闭,线程池会一直运行
        pools.shutdown();
    }
}

4、Callable和Runnable接口的区别

Callable接口中的Call方法有返回值,Runnable接口中的Run方法没有返回值

Callable接口中的Call方法有声明异常,Runnable接口中的Run方法没有异常


相关文章
|
6天前
|
安全 Java 调度
Java编程时多线程操作单核服务器可以不加锁吗?
Java编程时多线程操作单核服务器可以不加锁吗?
21 2
|
10天前
|
存储 缓存 Java
java线程内存模型底层实现原理
java线程内存模型底层实现原理
java线程内存模型底层实现原理
|
12天前
|
Java 开发者
Java中的多线程基础与应用
【9月更文挑战第22天】在Java的世界中,多线程是一块基石,它支撑着现代并发编程的大厦。本文将深入浅出地介绍Java中多线程的基本概念、创建方法以及常见的应用场景,帮助读者理解并掌握这一核心技术。
|
8天前
|
Java 调度
Java-Thread多线程的使用
这篇文章介绍了Java中Thread类多线程的创建、使用、生命周期、状态以及线程同步和死锁的概念和处理方法。
Java-Thread多线程的使用
|
14天前
|
Java
领略Lock接口的风采,通过实战演练,让你迅速掌握这门高深武艺,成为Java多线程领域的武林盟主
领略Lock接口的风采,通过实战演练,让你迅速掌握这门高深武艺,成为Java多线程领域的武林盟主
22 7
|
13天前
|
Java 程序员
Java中的多线程基础与实践
【9月更文挑战第21天】本文旨在引导读者深入理解Java多线程的核心概念,通过生动的比喻和实例,揭示线程创建、同步机制以及常见并发工具类的使用。文章将带领读者从理论到实践,逐步掌握如何在Java中高效地运用多线程技术。
|
11天前
|
Java 调度 开发者
Java中的多线程编程:从基础到实践
本文旨在深入探讨Java多线程编程的核心概念和实际应用,通过浅显易懂的语言解释多线程的基本原理,并结合实例展示如何在Java中创建、控制和管理线程。我们将从简单的线程创建开始,逐步深入到线程同步、通信以及死锁问题的解决方案,最终通过具体的代码示例来加深理解。无论您是Java初学者还是希望提升多线程编程技能的开发者,本文都将为您提供有价值的见解和实用的技巧。
15 2
|
13天前
|
Java 数据处理
Java中的多线程编程:从基础到实践
本文旨在深入探讨Java中的多线程编程,涵盖其基本概念、创建方法、同步机制及实际应用。通过对多线程基础知识的介绍和具体示例的演示,希望帮助读者更好地理解和应用Java多线程编程,提高程序的效率和性能。
19 1
|
6天前
|
Java 数据中心 微服务
Java高级知识:线程池隔离与信号量隔离的实战应用
在Java并发编程中,线程池隔离与信号量隔离是两种常用的资源隔离技术,它们在提高系统稳定性、防止系统过载方面发挥着重要作用。
6 0
|
8天前
|
Java 数据处理 调度
Java中的多线程编程:从基础到实践
本文深入探讨了Java中多线程编程的基本概念、实现方式及其在实际项目中的应用。首先,我们将了解什么是线程以及为何需要多线程编程。接着,文章将详细介绍如何在Java中创建和管理线程,包括继承Thread类、实现Runnable接口以及使用Executor框架等方法。此外,我们还将讨论线程同步和通信的问题,如互斥锁、信号量、条件变量等。最后,通过具体的示例展示了如何在实际项目中有效地利用多线程提高程序的性能和响应能力。
下一篇
无影云桌面