Java并发编程:从基础到高级应用

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

Java并发编程:从基础到高级应用

在这里插入图片描述

16.1 并发编程概述
16.1.1 学习目标与重点提示

学习目标:理解并发编程的基本概念,掌握线程的创建和使用方法,了解线程同步和通信的原理,学会使用并发工具类,掌握并发编程中的常见问题及解决方案。
重点:线程的创建与使用(继承Thread类、实现Runnable接口、使用Callable接口和FutureTask类)线程同步(synchronized关键字、Lock接口)线程通信(wait()、notify()、notifyAll()方法)并发工具类(Executor、ExecutorService、Future、Callable、Semaphore、CountDownLatch)

16.1.2 并发编程的基本概念

进程:进程是操作系统中的一个执行单元,是程序的一次执行过程。
线程:线程是进程中的一个执行单元,是程序执行的最小单位。
并发:并发是指多个线程同时执行,但在同一时刻只有一个线程在执行。
并行:并行是指多个线程同时执行,且在同一时刻有多个线程在执行。

16.2 线程的创建与使用

Java提供了三种创建线程的方法:继承Thread类、实现Runnable接口、使用Callable接口和FutureTask类。

16.2.1 继承Thread类

定义:继承Thread类是Java中最简单的创建线程的方法。
示例

class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("线程" + Thread.currentThread().getName() + "正在执行...");
    }
}

public class TestThread {
    public static void main(String[] args) {
        // 创建MyThread对象
        MyThread thread1 = new MyThread();
        MyThread thread2 = new MyThread();
        
        // 设置线程名
        thread1.setName("线程1");
        thread2.setName("线程2");
        
        // 启动线程
        thread1.start();
        thread2.start();
        
        // 输出主线程名
        System.out.println("主线程" + Thread.currentThread().getName() + "正在执行...");
    }
}

输出结果

线程1正在执行...
主线程main正在执行...
线程2正在执行...

✅ 结论:继承Thread类是Java中最简单的创建线程的方法,但由于Java是单继承的,这种方法有一定的局限性。

16.2.2 实现Runnable接口

定义:实现Runnable接口是Java中最常用的创建线程的方法。
示例

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("线程" + Thread.currentThread().getName() + "正在执行...");
    }
}

public class TestRunnable {
    public static void main(String[] args) {
        // 创建MyRunnable对象
        MyRunnable runnable = new MyRunnable();
        
        // 创建Thread对象
        Thread thread1 = new Thread(runnable, "线程1");
        Thread thread2 = new Thread(runnable, "线程2");
        
        // 启动线程
        thread1.start();
        thread2.start();
        
        // 输出主线程名
        System.out.println("主线程" + Thread.currentThread().getName() + "正在执行...");
    }
}

输出结果

线程1正在执行...
主线程main正在执行...
线程2正在执行...

✅ 结论:实现Runnable接口是Java中最常用的创建线程的方法,由于Java是多实现的,这种方法没有局限性。

16.2.3 使用Callable接口和FutureTask类

定义:使用Callable接口和FutureTask类是Java中最灵活的创建线程的方法。
示例

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

class MyCallable implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        System.out.println("线程" + Thread.currentThread().getName() + "正在执行...");
        return 100;
    }
}

public class TestCallable {
    public static void main(String[] args) {
        // 创建MyCallable对象
        MyCallable callable = new MyCallable();
        
        // 创建FutureTask对象
        FutureTask<Integer> futureTask = new FutureTask<>(callable);
        
        // 创建Thread对象
        Thread thread = new Thread(futureTask, "线程1");
        
        // 启动线程
        thread.start();
        
        try {
            // 获取线程返回值
            Integer result = futureTask.get();
            System.out.println("线程返回值:" + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        // 输出主线程名
        System.out.println("主线程" + Thread.currentThread().getName() + "正在执行...");
    }
}

输出结果

线程1正在执行...
线程返回值:100
主线程main正在执行...

✅ 结论:使用Callable接口和FutureTask类是Java中最灵活的创建线程的方法,这种方法可以获取线程的返回值。

16.3 线程同步

线程同步是指多个线程同时访问共享资源时,保证资源的一致性和完整性。Java提供了两种线程同步的方法:synchronized关键字和Lock接口。

16.3.1 synchronized关键字

定义:synchronized关键字是Java中最常用的线程同步方法。
示例

class Counter {
    private int count;
    
    public synchronized void increment() {
        count++;
    }
    
    public synchronized void decrement() {
        count--;
    }
    
    public synchronized int getCount() {
        return count;
    }
}

class MyRunnable implements Runnable {
    private Counter counter;
    
    public MyRunnable(Counter counter) {
        this.counter = counter;
    }
    
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            counter.increment();
        }
    }
}

public class TestSynchronized {
    public static void main(String[] args) {
        // 创建Counter对象
        Counter counter = new Counter();
        
        // 创建MyRunnable对象
        MyRunnable runnable = new MyRunnable(counter);
        
        // 创建Thread对象
        Thread thread1 = new Thread(runnable, "线程1");
        Thread thread2 = new Thread(runnable, "线程2");
        
        // 启动线程
        thread1.start();
        thread2.start();
        
        try {
            // 等待线程结束
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        // 输出count的值
        System.out.println("count的值:" + counter.getCount());
    }
}

输出结果

count的值:2000

✅ 结论:synchronized关键字是Java中最常用的线程同步方法,这种方法可以保证资源的一致性和完整性。

16.3.2 Lock接口

定义:Lock接口是Java中最灵活的线程同步方法。
示例

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class Counter {
    private int count;
    private Lock lock = new ReentrantLock();
    
    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }
    
    public void decrement() {
        lock.lock();
        try {
            count--;
        } finally {
            lock.unlock();
        }
    }
    
    public int getCount() {
        lock.lock();
        try {
            return count;
        } finally {
            lock.unlock();
        }
    }
}

class MyRunnable implements Runnable {
    private Counter counter;
    
    public MyRunnable(Counter counter) {
        this.counter = counter;
    }
    
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            counter.increment();
        }
    }
}

public class TestLock {
    public static void main(String[] args) {
        // 创建Counter对象
        Counter counter = new Counter();
        
        // 创建MyRunnable对象
        MyRunnable runnable = new MyRunnable(counter);
        
        // 创建Thread对象
        Thread thread1 = new Thread(runnable, "线程1");
        Thread thread2 = new Thread(runnable, "线程2");
        
        // 启动线程
        thread1.start();
        thread2.start();
        
        try {
            // 等待线程结束
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        // 输出count的值
        System.out.println("count的值:" + counter.getCount());
    }
}

输出结果

count的值:2000

✅ 结论:Lock接口是Java中最灵活的线程同步方法,这种方法可以保证资源的一致性和完整性。

16.4 线程通信

线程通信是指多个线程之间进行信息交换的过程。Java提供了三种线程通信的方法:wait()、notify()、notifyAll()方法。

16.4.1 wait()、notify()、notifyAll()方法

定义:wait()、notify()、notifyAll()方法是Java中最常用的线程通信方法。
示例

class Message {
    private String content;
    private boolean flag = false;
    
    public synchronized void write(String content) {
        while (flag) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
        this.content = content;
        flag = true;
        notifyAll();
    }
    
    public synchronized String read() {
        while (!flag) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
        flag = false;
        notifyAll();
        return content;
    }
}

class Writer implements Runnable {
    private Message message;
    
    public Writer(Message message) {
        this.message = message;
    }
    
    @Override
    public void run() {
        String[] messages = {"Hello", "World", "Java"};
        for (String content : messages) {
            message.write(content);
            System.out.println("写入消息:" + content);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Reader implements Runnable {
    private Message message;
    
    public Reader(Message message) {
        this.message = message;
    }
    
    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            String content = message.read();
            System.out.println("读取消息:" + content);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class TestThreadCommunication {
    public static void main(String[] args) {
        // 创建Message对象
        Message message = new Message();
        
        // 创建Writer和Reader对象
        Writer writer = new Writer(message);
        Reader reader = new Reader(message);
        
        // 创建Thread对象
        Thread thread1 = new Thread(writer, "写入线程");
        Thread thread2 = new Thread(reader, "读取线程");
        
        // 启动线程
        thread1.start();
        thread2.start();
    }
}

输出结果

写入消息:Hello
读取消息:Hello
写入消息:World
读取消息:World
写入消息:Java
读取消息:Java

✅ 结论:wait()、notify()、notifyAll()方法是Java中最常用的线程通信方法,这种方法可以实现多个线程之间的信息交换。

16.5 并发工具类

Java提供了丰富的并发工具类,用于简化并发编程。

16.5.1 Executor、ExecutorService、Future、Callable

定义:Executor、ExecutorService、Future、Callable是Java中最常用的并发工具类。
示例

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

class MyCallable implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        System.out.println("线程" + Thread.currentThread().getName() + "正在执行...");
        return 100;
    }
}

public class TestExecutor {
    public static void main(String[] args) {
        // 创建ExecutorService对象
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        
        // 创建MyCallable对象
        MyCallable callable = new MyCallable();
        
        // 提交任务
        Future<Integer> future1 = executorService.submit(callable);
        Future<Integer> future2 = executorService.submit(callable);
        
        try {
            // 获取任务返回值
            Integer result1 = future1.get();
            Integer result2 = future2.get();
            
            System.out.println("任务1返回值:" + result1);
            System.out.println("任务2返回值:" + result2);
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        // 关闭ExecutorService
        executorService.shutdown();
    }
}

输出结果

线程pool-1-thread-1正在执行...
线程pool-1-thread-2正在执行...
任务1返回值:100
任务2返回值:100

✅ 结论:Executor、ExecutorService、Future、Callable是Java中最常用的并发工具类,这种方法可以简化并发编程。

16.5.2 Semaphore

定义:Semaphore是Java中最常用的并发工具类之一,用于控制同时访问共享资源的线程数。
示例

import java.util.concurrent.Semaphore;

class MyRunnable implements Runnable {
    private Semaphore semaphore;
    
    public MyRunnable(Semaphore semaphore) {
        this.semaphore = semaphore;
    }
    
    @Override
    public void run() {
        try {
            // 获取许可
            semaphore.acquire();
            
            System.out.println("线程" + Thread.currentThread().getName() + "正在执行...");
            
            // 模拟线程执行时间
            Thread.sleep(1000);
            
            System.out.println("线程" + Thread.currentThread().getName() + "执行完毕...");
            
            // 释放许可
            semaphore.release();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class TestSemaphore {
    public static void main(String[] args) {
        // 创建Semaphore对象
        Semaphore semaphore = new Semaphore(2);
        
        // 创建MyRunnable对象
        MyRunnable runnable = new MyRunnable(semaphore);
        
        // 创建Thread对象
        Thread thread1 = new Thread(runnable, "线程1");
        Thread thread2 = new Thread(runnable, "线程2");
        Thread thread3 = new Thread(runnable, "线程3");
        
        // 启动线程
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

输出结果

线程1正在执行...
线程2正在执行...
线程1执行完毕...
线程2执行完毕...
线程3正在执行...
线程3执行完毕...

✅ 结论:Semaphore是Java中最常用的并发工具类之一,这种方法可以控制同时访问共享资源的线程数。

16.5.3 CountDownLatch

定义:CountDownLatch是Java中最常用的并发工具类之一,用于等待多个线程完成后再执行后续操作。
示例

import java.util.concurrent.CountDownLatch;

class MyRunnable implements Runnable {
    private CountDownLatch countDownLatch;
    
    public MyRunnable(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }
    
    @Override
    public void run() {
        try {
            System.out.println("线程" + Thread.currentThread().getName() + "正在执行...");
            
            // 模拟线程执行时间
            Thread.sleep(1000);
            
            System.out.println("线程" + Thread.currentThread().getName() + "执行完毕...");
            
            // 计数减1
            countDownLatch.countDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class TestCountDownLatch {
    public static void main(String[] args) {
        // 创建CountDownLatch对象
        CountDownLatch countDownLatch = new CountDownLatch(2);
        
        // 创建MyRunnable对象
        MyRunnable runnable = new MyRunnable(countDownLatch);
        
        // 创建Thread对象
        Thread thread1 = new Thread(runnable, "线程1");
        Thread thread2 = new Thread(runnable, "线程2");
        
        // 启动线程
        thread1.start();
        thread2.start();
        
        try {
            // 等待计数减到0
            countDownLatch.await();
            
            System.out.println("所有线程执行完毕...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

输出结果

线程1正在执行...
线程2正在执行...
线程1执行完毕...
线程2执行完毕...
所有线程执行完毕...

✅ 结论:CountDownLatch是Java中最常用的并发工具类之一,这种方法可以等待多个线程完成后再执行后续操作。

总结

本章我们学习了Java的并发编程,包括线程的创建与使用、线程同步、线程通信、并发工具类等内容。其中,线程的创建与使用(继承Thread类、实现Runnable接口、使用Callable接口和FutureTask类)、线程同步(synchronized关键字、Lock接口)、线程通信(wait()、notify()、notifyAll()方法)、并发工具类(Executor、ExecutorService、Future、Callable、Semaphore、CountDownLatch)是本章的重点内容。从下一章开始,我们将学习Java的Web开发、Spring框架等内容。

您可能感兴趣的与本文相关的镜像

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值