Java多线程从基础到高级应用示例小结

 更新时间:2026年01月21日 15:33:03   作者:星河耀银海  
本章介绍了Java多线程编程的基础知识,包括线程的创建与管理、线程同步、线程通信和线程池,重点内容包括线程的三种创建方式,通过本章的学习,读者掌握了Java多线程编程的基本技能,感兴趣的朋友跟随小编一起看看吧

Java多线程:从基础到高级应用

11.1 多线程概述

11.1.1 学习目标与重点提示

学习目标:理解多线程的基本概念,掌握线程的创建与管理方法,了解线程同步与通信的实现方式,掌握线程池的使用方法。
重点:线程的创建方式(继承Thread类、实现Runnable接口、使用Callable和Future)线程同步(synchronized、Lock)线程通信(wait/notify、await/signal)线程池(Executor、ThreadPoolExecutor)

11.1.2 多线程的基本概念

进程:一个正在运行的程序,包含代码、数据和资源。
线程:进程内部的一个执行单元,共享进程的资源。
多线程:一个进程包含多个线程,同时执行多个任务。

多线程的优势:

  • 提高程序的执行效率。
  • 充分利用CPU资源。
  • 提高程序的响应速度。

多线程的劣势:

  • 增加了程序的复杂度。
  • 容易出现线程安全问题。

11.2 线程的创建与管理

Java中创建线程的方式有三种:继承Thread类、实现Runnable接口、使用Callable和Future。

11.2.1 继承Thread类

定义:继承Thread类,重写run()方法,创建Thread子类的对象,调用start()方法启动线程。
示例

class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + ": " + i);
        }
    }
}
public class TestThread {
    public static void main(String[] args) {
        MyThread thread1 = new MyThread();
        MyThread thread2 = new MyThread();
        thread1.start();
        thread2.start();
    }
}

输出结果

Thread-0: 0
Thread-0: 1
Thread-1: 0
Thread-1: 1
Thread-0: 2
Thread-0: 3
Thread-1: 2
Thread-0: 4
Thread-1: 3
Thread-0: 5
Thread-0: 6
Thread-1: 4
Thread-0: 7
Thread-1: 5
Thread-0: 8
Thread-0: 9
Thread-1: 6
Thread-1: 7
Thread-1: 8
Thread-1: 9

✅ 结论:继承Thread类的方式简单,但Java不支持多继承,因此这种方式有局限性。

11.2.2 实现Runnable接口

定义:实现Runnable接口,重写run()方法,创建Runnable接口的实现类的对象,将该对象作为参数传递给Thread类的构造方法,调用start()方法启动线程。
示例

class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + ": " + i);
        }
    }
}
public class TestRunnable {
    public static void main(String[] args) {
        MyRunnable runnable = new MyRunnable();
        Thread thread1 = new Thread(runnable);
        Thread thread2 = new Thread(runnable);
        thread1.start();
        thread2.start();
    }
}

输出结果

Thread-0: 0
Thread-0: 1
Thread-1: 0
Thread-1: 1
Thread-0: 2
Thread-0: 3
Thread-1: 2
Thread-0: 4
Thread-1: 3
Thread-0: 5
Thread-0: 6
Thread-1: 4
Thread-0: 7
Thread-1: 5
Thread-0: 8
Thread-0: 9
Thread-1: 6
Thread-1: 7
Thread-1: 8
Thread-1: 9

✅ 结论:实现Runnable接口的方式避免了Java不支持多继承的限制,但无法返回线程执行结果。

11.2.3 使用Callable和Future

定义:实现Callable接口,重写call()方法,创建Callable接口的实现类的对象,将该对象作为参数传递给FutureTask类的构造方法,将FutureTask类的对象作为参数传递给Thread类的构造方法,调用start()方法启动线程,通过FutureTask类的get()方法获取线程执行结果。
示例

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
class MyCallable implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 0; i <= 100; i++) {
            sum += i;
        }
        return sum;
    }
}
public class TestCallable {
    public static void main(String[] args) {
        MyCallable callable = new MyCallable();
        FutureTask<Integer> futureTask = new FutureTask<>(callable);
        Thread thread = new Thread(futureTask);
        thread.start();
        try {
            int result = futureTask.get();
            System.out.println("1到100的和:" + result);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
}

输出结果

1到100的和:5050

✅ 结论:使用Callable和Future的方式可以返回线程执行结果,但需要使用FutureTask类。

11.3 线程同步

线程同步是指多个线程同时访问共享资源时,保证资源的一致性和正确性。

11.3.1 synchronized关键字

定义:synchronized关键字用于实现线程同步,分为同步方法和同步块。
示例

class Count {
    private int count = 0;
    public synchronized void increment() {
        count++;
        System.out.println(Thread.currentThread().getName() + ": " + count);
    }
}
class MyThread extends Thread {
    private Count count;
    public MyThread(Count count) {
        this.count = count;
    }
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            count.increment();
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class TestSynchronized {
    public static void main(String[] args) {
        Count count = new Count();
        MyThread thread1 = new MyThread(count);
        MyThread thread2 = new MyThread(count);
        thread1.start();
        thread2.start();
    }
}

输出结果

Thread-0: 1
Thread-1: 2
Thread-0: 3
Thread-1: 4
Thread-0: 5
Thread-1: 6
Thread-0: 7
Thread-1: 8
Thread-0: 9
Thread-1: 10
Thread-0: 11
Thread-1: 12
Thread-0: 13
Thread-1: 14
Thread-0: 15
Thread-1: 16
Thread-0: 17
Thread-1: 18
Thread-0: 19
Thread-1: 20

✅ 结论:synchronized关键字可以保证线程同步,但性能较低。

11.3.2 Lock接口

定义:Lock接口用于实现线程同步,提供了更灵活的同步方式,如可重入锁、读写锁等。
示例

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Count {
    private int count = 0;
    private Lock lock = new ReentrantLock();
    public void increment() {
        lock.lock();
        try {
            count++;
            System.out.println(Thread.currentThread().getName() + ": " + count);
        } finally {
            lock.unlock();
        }
    }
}
class MyThread extends Thread {
    private Count count;
    public MyThread(Count count) {
        this.count = count;
    }
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            count.increment();
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class TestLock {
    public static void main(String[] args) {
        Count count = new Count();
        MyThread thread1 = new MyThread(count);
        MyThread thread2 = new MyThread(count);
        thread1.start();
        thread2.start();
    }
}

输出结果

Thread-0: 1
Thread-1: 2
Thread-0: 3
Thread-1: 4
Thread-0: 5
Thread-1: 6
Thread-0: 7
Thread-1: 8
Thread-0: 9
Thread-1: 10
Thread-0: 11
Thread-1: 12
Thread-0: 13
Thread-1: 14
Thread-0: 15
Thread-1: 16
Thread-0: 17
Thread-1: 18
Thread-0: 19
Thread-1: 20

✅ 结论:Lock接口可以提供更灵活的同步方式,但需要手动释放锁。

11.4 线程通信

线程通信是指多个线程之间的协作,如生产者-消费者模型。

11.4.1 wait/notify方法

定义:wait/notify方法用于实现线程通信,wait()方法使线程进入等待状态,notify()方法唤醒等待的线程。
示例

class Warehouse {
    private int count = 0;
    private final int MAX_COUNT = 10;
    public synchronized void produce() throws InterruptedException {
        while (count == MAX_COUNT) {
            wait();
        }
        count++;
        System.out.println(Thread.currentThread().getName() + ": 生产了一个产品,当前产品数量:" + count);
        notifyAll();
    }
    public synchronized void consume() throws InterruptedException {
        while (count == 0) {
            wait();
        }
        count--;
        System.out.println(Thread.currentThread().getName() + ": 消费了一个产品,当前产品数量:" + count);
        notifyAll();
    }
}
class Producer extends Thread {
    private Warehouse warehouse;
    public Producer(Warehouse warehouse) {
        this.warehouse = warehouse;
    }
    @Override
    public void run() {
        try {
            for (int i = 0; i < 20; i++) {
                warehouse.produce();
                Thread.sleep(100);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
class Consumer extends Thread {
    private Warehouse warehouse;
    public Consumer(Warehouse warehouse) {
        this.warehouse = warehouse;
    }
    @Override
    public void run() {
        try {
            for (int i = 0; i < 20; i++) {
                warehouse.consume();
                Thread.sleep(100);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
public class TestWaitNotify {
    public static void main(String[] args) {
        Warehouse warehouse = new Warehouse();
        Producer producer1 = new Producer(warehouse);
        Producer producer2 = new Producer(warehouse);
        Consumer consumer1 = new Consumer(warehouse);
        Consumer consumer2 = new Consumer(warehouse);
        producer1.start();
        producer2.start();
        consumer1.start();
        consumer2.start();
    }
}

输出结果

Thread-0: 生产了一个产品,当前产品数量:1
Thread-1: 生产了一个产品,当前产品数量:2
Thread-2: 消费了一个产品,当前产品数量:1
Thread-3: 消费了一个产品,当前产品数量:0
Thread-0: 生产了一个产品,当前产品数量:1
Thread-1: 生产了一个产品,当前产品数量:2
Thread-2: 消费了一个产品,当前产品数量:1
Thread-3: 消费了一个产品,当前产品数量:0
...

✅ 结论:wait/notify方法可以实现线程通信,但需要在同步块中使用。

11.4.2 await/signal方法

定义:await/signal方法用于实现线程通信,await()方法使线程进入等待状态,signal()方法唤醒等待的线程。
示例

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Warehouse {
    private int count = 0;
    private final int MAX_COUNT = 10;
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    public void produce() throws InterruptedException {
        lock.lock();
        try {
            while (count == MAX_COUNT) {
                condition.await();
            }
            count++;
            System.out.println(Thread.currentThread().getName() + ": 生产了一个产品,当前产品数量:" + count);
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }
    public void consume() throws InterruptedException {
        lock.lock();
        try {
            while (count == 0) {
                condition.await();
            }
            count--;
            System.out.println(Thread.currentThread().getName() + ": 消费了一个产品,当前产品数量:" + count);
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }
}
class Producer extends Thread {
    private Warehouse warehouse;
    public Producer(Warehouse warehouse) {
        this.warehouse = warehouse;
    }
    @Override
    public void run() {
        try {
            for (int i = 0; i < 20; i++) {
                warehouse.produce();
                Thread.sleep(100);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
class Consumer extends Thread {
    private Warehouse warehouse;
    public Consumer(Warehouse warehouse) {
        this.warehouse = warehouse;
    }
    @Override
    public void run() {
        try {
            for (int i = 0; i < 20; i++) {
                warehouse.consume();
                Thread.sleep(100);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
public class TestAwaitSignal {
    public static void main(String[] args) {
        Warehouse warehouse = new Warehouse();
        Producer producer1 = new Producer(warehouse);
        Producer producer2 = new Producer(warehouse);
        Consumer consumer1 = new Consumer(warehouse);
        Consumer consumer2 = new Consumer(warehouse);
        producer1.start();
        producer2.start();
        consumer1.start();
        consumer2.start();
    }
}

输出结果

Thread-0: 生产了一个产品,当前产品数量:1
Thread-1: 生产了一个产品,当前产品数量:2
Thread-2: 消费了一个产品,当前产品数量:1
Thread-3: 消费了一个产品,当前产品数量:0
Thread-0: 生产了一个产品,当前产品数量:1
Thread-1: 生产了一个产品,当前产品数量:2
Thread-2: 消费了一个产品,当前产品数量:1
Thread-3: 消费了一个产品,当前产品数量:0
...

✅ 结论:await/signal方法可以提供更灵活的线程通信方式,但需要使用Lock接口。

11.5 线程池

线程池是一种管理线程的方式,用于减少线程的创建和销毁开销。

11.5.1 Executor框架

定义:Executor框架是Java提供的线程池管理框架,包括Executor、ExecutorService、ThreadPoolExecutor等类。
示例

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class MyRunnable implements Runnable {
    private int taskId;
    public MyRunnable(int taskId) {
        this.taskId = taskId;
    }
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + ": 执行任务" + taskId);
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + ": 任务" + taskId + "完成");
    }
}
public class TestExecutor {
    public static void main(String[] args) {
        // 创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        // 提交任务
        for (int i = 0; i < 10; i++) {
            executorService.submit(new MyRunnable(i));
        }
        // 关闭线程池
        executorService.shutdown();
    }
}

输出结果

pool-1-thread-1: 执行任务0
pool-1-thread-2: 执行任务1
pool-1-thread-3: 执行任务2
pool-1-thread-1: 任务0完成
pool-1-thread-1: 执行任务3
pool-1-thread-2: 任务1完成
pool-1-thread-2: 执行任务4
pool-1-thread-3: 任务2完成
pool-1-thread-3: 执行任务5
pool-1-thread-1: 任务3完成
pool-1-thread-1: 执行任务6
pool-1-thread-2: 任务4完成
pool-1-thread-2: 执行任务7
pool-1-thread-3: 任务5完成
pool-1-thread-3: 执行任务8
pool-1-thread-1: 任务6完成
pool-1-thread-1: 执行任务9
pool-1-thread-2: 任务7完成
pool-1-thread-3: 任务8完成
pool-1-thread-1: 任务9完成

✅ 结论:Executor框架可以方便地管理线程池,但需要根据实际需求选择合适的线程池类型。

总结

本章我们学习了Java的多线程,包括线程的创建与管理、线程同步、线程通信、线程池等内容。其中,线程的创建方式(继承Thread类、实现Runnable接口、使用Callable和Future)、线程同步(synchronized、Lock)、线程通信(wait/notify、await/signal)、线程池(Executor、ThreadPoolExecutor)是本章的重点内容。从下一章开始,我们将学习Java的网络编程、数据库编程等内容。

到此这篇关于Java多线程从基础到高级应用示例小结的文章就介绍到这了,更多相关java多线程应用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java多线程高并发中解决ArrayList与HashSet和HashMap不安全的方案

    Java多线程高并发中解决ArrayList与HashSet和HashMap不安全的方案

    ArrayList实现了可变大小的数组。它允许所有元素,包括null。ArrayList没有同步,HashMap和Hashtable类似,不同之处在于HashMap是非同步的,并且允许null,关于HashSet有一件事应该牢记,即就条目数和容量之和来讲,迭代是线性的,接下来让我们详细来了解吧
    2021-11-11
  • 在IDEA中配置Selenium和WebDriver的具体操作

    在IDEA中配置Selenium和WebDriver的具体操作

    在自动化测试领域Selenium是一款非常流行的开源工具,它支持多种浏览器,并提供了丰富的API供开发者使用,而WebDriver则是Selenium的一个重要组件,它负责驱动浏览器执行测试脚本,这篇文章主要给大家介绍了在IDEA中配置Selenium和WebDriver的具体操作,需要的朋友可以参考下
    2024-10-10
  • Mybatis之动态SQL使用小结(全网最新)

    Mybatis之动态SQL使用小结(全网最新)

    MyBatis令人喜欢的一大特性就是动态SQL, 在使用JDBC的过程中, 根据条件进行SQL的拼接是很麻烦且很容易出错的,MyBatis通过OGNL来进行动态SQL的使用解决了这个麻烦,对Mybatis动态SQL相关知识感兴趣的朋友跟随小编一起看看吧
    2024-05-05
  • java 装饰模式(Decorator Pattern)详解

    java 装饰模式(Decorator Pattern)详解

    这篇文章主要介绍了java 装饰模式(Decorator Pattern)详解的相关资料,需要的朋友可以参考下
    2016-10-10
  • Spring Boot实现文件上传示例代码

    Spring Boot实现文件上传示例代码

    本篇文章主要介绍了Spring Boot实现文件上传示例代码,可以实现单文件和多文件的上传,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-03-03
  • 使用BigInteger实现除法取余

    使用BigInteger实现除法取余

    这篇文章主要介绍了使用BigInteger实现除法取余操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • Java中实现线程的超时中断方法实例

    Java中实现线程的超时中断方法实例

    之前在使用Java实现熔断降级组件的时候,需要实现接口请求的超时中断,通过查找相关资料了解了相关的方法,下面这篇文章主要给大家介绍了关于Java中实现线程的超时中断的相关资料,需要的朋友可以参考下
    2018-06-06
  • java程序员如何编写更好的单元测试的7个技巧

    java程序员如何编写更好的单元测试的7个技巧

    测试是开发的一个非常重要的方面,可以在很大程度上决定一个应用程序的命运。良好的测试可以在早期捕获导致应用程序崩溃的问题,但较差的测试往往总是导致故障和停机。本文主要介绍java程序员编写更好的单元测试的7个技巧。下面跟着小编一起来看下吧
    2017-03-03
  • Java中fail-fast和fail-safe的使用

    Java中fail-fast和fail-safe的使用

    fail-fast和fail-safe是两种不同的迭代器行为,特别是在遍历集合时遇到并发修改的情况,本文主要介绍了Java中fail-fast和fail-safe的使用,感兴趣的可以了解一下
    2024-08-08
  • java中的定时器和多线程

    java中的定时器和多线程

    这篇文章主要介绍了java中的定时器和多线程用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01

最新评论