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方法没有异常


相关文章
|
23小时前
|
缓存 Java 调度
Java并发编程:深入理解线程池
【4月更文挑战第30天】 在Java并发编程中,线程池是一种重要的工具,它可以帮助我们有效地管理线程,提高系统性能。本文将深入探讨Java线程池的工作原理,如何使用它,以及如何根据实际需求选择合适的线程池策略。
|
1天前
|
Java
Java并发编程:深入理解线程池
【4月更文挑战第30天】 本文将深入探讨Java中的线程池,解析其原理、使用场景以及如何合理地利用线程池提高程序性能。我们将从线程池的基本概念出发,介绍其内部工作机制,然后通过实例演示如何创建和使用线程池。最后,我们将讨论线程池的优缺点以及在实际应用中需要注意的问题。
|
1天前
|
设计模式 算法 安全
Java多线程编程实战:从入门到精通
【4月更文挑战第30天】本文介绍了Java多线程编程的基础,包括线程概念、创建线程(继承`Thread`或实现`Runnable`)、线程生命周期。还讨论了线程同步与锁(同步代码块、`ReentrantLock`)、线程间通信(等待/通知、并发集合)以及实战技巧,如使用线程池、线程安全设计模式和避免死锁。性能优化方面,建议减少锁粒度和使用非阻塞算法。理解这些概念和技术对于编写高效、可靠的多线程程序至关重要。
|
1天前
|
Java 调度 开发者
Java中的多线程编程:基础知识与实践
【4月更文挑战第30天】 在现代软件开发中,多线程编程是提高程序性能和响应能力的关键。Java作为一款广泛使用的编程语言,提供了丰富的多线程支持。本文将介绍Java多线程的基础概念、实现方法以及常见问题的解决策略。我们将从线程的创建和管理入手,逐步深入到同步机制、死锁避免以及高级并发工具类的应用。通过实例代码演示和理论分析,旨在帮助读者掌握Java多线程编程的核心技能,提升软件项目的并行处理能力。
|
1天前
|
Java
java多线程售票例子
java多线程售票例子
|
1天前
|
Java 程序员
Java中的多线程编程与性能优化
【4月更文挑战第30天】本文主要探讨了Java中的多线程编程以及如何通过多线程技术来提升程序的性能。首先,我们将介绍多线程的基本概念和原理,然后深入探讨Java中实现多线程的两种主要方式:继承Thread类和实现Runnable接口。接着,我们将讨论多线程中的同步问题,包括synchronized关键字和Lock锁。最后,我们将探讨如何通过线程池来管理和优化线程,以及如何避免常见的多线程问题。
|
1天前
|
Java
Java并发编程:深入理解线程池
【4月更文挑战第30天】本文将深入探讨Java并发编程中的一个重要主题——线程池。我们将从线程池的基本概念入手,了解其工作原理和优势,然后详细介绍如何使用Java的Executor框架创建和管理线程池。最后,我们将讨论一些高级主题,如自定义线程工厂和拒绝策略。通过本文的学习,你将能够更好地理解和使用Java的线程池,提高你的并发编程能力。
|
1天前
|
存储 安全 Java
深入理解Java并发编程:线程安全与性能优化
【4月更文挑战第30天】在Java开发中,并发编程是一个复杂而又关键的领域。它允许多个线程同时执行,从而提高程序性能和资源利用率。然而,并发编程也带来了许多挑战,如数据不一致、死锁和线程安全问题。本文将深入探讨Java并发编程的核心概念,包括线程安全和性能优化策略。我们将通过实例分析如何在保证线程安全的同时提高程序性能,为Java开发者提供实用的指导。
|
1天前
|
Java 程序员 开发者
深入理解Java并发编程:线程同步与锁机制
【4月更文挑战第30天】 在多线程的世界中,确保数据的一致性和线程间的有效通信是至关重要的。本文将深入探讨Java并发编程中的核心概念——线程同步与锁机制。我们将从基本的synchronized关键字开始,逐步过渡到更复杂的ReentrantLock类,并探讨它们如何帮助我们在多线程环境中保持数据完整性和避免常见的并发问题。文章还将通过示例代码,展示这些同步工具在实际开发中的应用,帮助读者构建对Java并发编程深层次的理解。
|
1天前
|
安全 Java 调度
深入理解Java并发编程:线程安全与性能优化
【4月更文挑战第30天】本文将深入探讨Java并发编程的核心概念,包括线程安全、同步机制、锁优化以及性能调优。我们将通过实例分析如何确保多线程环境下的数据一致性,同时介绍一些常见的并发模式和最佳实践,旨在帮助开发者在保证线程安全的同时,提升系统的性能和响应能力。