Java三大线程同步机制代码实战指南

 更新时间:2026年03月07日 10:21:00   作者:程序员码小跳  
文章介绍了Java线程的五种状态(新建、就绪、运行、阻塞、死亡),以及线程的创建方式(继承Thread类、实现Runnable接口、实现Callable接口),本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

线程状态

  • 新建(New):当程序使用 new 关键字、Thread 类或其子类建立一个线程对象后,该线程就处于新建状态。它保持这个状态直到程序 start() 这个线程。(new MyThread)
  • 就绪(Runnable 或Ready to Run):当线程对象调用了start()方法之后,该线程处于就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。(new MyThread.start() )
  • 运行(Running):如果处于就绪状态的线程获得了 CPU,开始执行 run()方法的线程执行体,则该线程处于运行状态。
  • 阻塞 (Blocked):如果一个线程执行了sleep、suspend等方法,失去CPU所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。
  • 死亡(Dead):线程会以下面三种方式结束,结束后就是死亡状态。
    • 正常结束:run()或 call()方法执行完成,线程正常结束。
    • 异常结束:线程抛出一个未捕获的 Exception 或 Error。
    • 调用结束:直接调用该线程的 stop()方法来结束该线程—该方法通常容易导致死锁,不推荐使用

创建线程

继承Thread类[无入参、无返回值]

实现步骤:

1.创建一个Thread类的子类 class MyThread extends Thread
2.在Thread类的子类中重写Thread类中的run()方法
3.创建Thread类的子类对象 MyThread t1 = new MyThread();
4.调用Thread类中的方法start()方法,开启新的线程,执行run方法 t1.start()
class MyThread extends Thread {
    @Override
    public void run() {
    }
}
public class demo21Thread01 {
    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        t1.start();
    }
}

实现Runnable接口[无入参,无返回值]

实现步骤:

1.创建一个Runnable接口的实现类 class myThread implements Runnable

2.在实现类中重写Runnable接口的run方法

3.创建一个Runnable接口的实现类对象 myThread t1 = new myThread();

4.创建Thread类对象,构造方法中传递Runnable接口的实现类对象Thread t=new Thread(t1);

5.调用Thread类中的start方法,开启新的线程执行run方法 t.start()

class myThread02 implements Runnable {
    public void run() {
    }
}
public class demo21Thread01 {
    public static void main(String args[]) throws InterruptedException {
        myThread02 mythread = new myThread02();
        Thread t = new Thread(mythread);
        t.start();
    }
}

实现Callable接口[无入参,有返回值]

class MyTask implements Callable<String> {
    @Override
    public String call() throws Exception {
        try {
            // 模拟业务处理
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "success";
    }
}
public class demo21Thread01 {
    public static void main(String[] args) throws Exception {
        // 1、callable怎么用,引入FutureTask初始化
        FutureTask<String> futureTask = new FutureTask<>(new MyTask());
        new Thread(futureTask).start();
        // 2、FutureTask线程启动,与main线程互不干扰
        while (!futureTask.isDone()) {
        }
        // 3、获得返回值:get方法尽量放在后面,一旦调用,线程等待等到执行完毕,会导致堵塞
        String value = futureTask.get();
        System.out.println("MyData的返回值:" + value);
    }
}

通过线程池方式

ExecutorService es= Executors.newCachedThreadPool();		//缓存型线程池
ExecutorService es= Executors.newFixedThreadPool(2);		//固定型线程池
ExecutorService es=Executors.newSingleThreadExecutor();  	//单线程型线程池
以上三种通过es.submit(new MyRunable03(i));提交任务
ScheduledExecutorService es = Executors.newScheduledThreadPool(3);//延迟执行或重复执行型线程池
通过es.schedule(new myRunnable(i), 2, TimeUnit.SECONDS);提交任务

通过lambda表达式

new Thread(() -> {
    System.out.println("程序已启动");
}).start();

线程同步

3种让线程等待和唤醒的方法

方式1: Object中的wait()线程等待、notify()唤醒线程【PS:必须配合synchronized】

方式2: Condition的await()线程等待、signal()唤醒线程【PS:必须配合ReentrantLock】

方式3: LockSupport的park()线程等待、unpark()唤醒线程

package thread;
/*
 * 两个线依次次输出1 2 3 4
 */
public class ThreadSyncTest2 {
    // 使用专用锁对象(不可变)
    private static Object LOCK = new Object();
    private static int num = 1;
    public static void main(String[] args) {
        new Thread(() -> {
            while (num <= 10) {
                try {
                    synchronized (LOCK) {
                        if (num % 2 == 0) {
                            System.out.println("偶数线程A: " + num++);
                            LOCK.notify();
                        } else {
                            LOCK.wait();
                        }
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }, "偶数线程A").start();
        new Thread(() -> {
            while (num <= 10) {
                try {
                    synchronized (LOCK) {
                        if (num % 2 == 1) {
                            System.out.println("基数线程B: " + num++);
                            LOCK.notify();
                        } else {
                            LOCK.wait();
                        }
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }, "基数线程B").start();
    }
}
package thread;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/*
 * 两个线程一次输出1 2 3 4
 */
public class ThreadSyncTest3 {
    private static int num = 1;
    // 锁与条件变量
    private static final ReentrantLock LOCK = new ReentrantLock();
    private static final Condition ODD_COND = LOCK.newCondition();    // 奇数条件队列
    private static final Condition EVEN_COND = LOCK.newCondition();    // 偶数条件队列
    public static void main(String[] args) {
        new Thread(() -> {
            while (num <= 10) {
                LOCK.lock();
                try {
                    if (num % 2 == 0) {
                        System.out.println("偶数线程A: " + num++);
                        ODD_COND.signal();
                    } else {
                        EVEN_COND.await();
                    }
                } catch (InterruptedException e) {
                    break;
                } finally {
                    LOCK.unlock();
                }
            }
            EVEN_COND.signal();
        }, "偶数线程A").start();
        new Thread(() -> {
            while (num <= 10) {
                LOCK.lock();
                try {
                    if (num % 2 == 1) {
                        System.out.println("基数线程B: " + num++);
                        EVEN_COND.signal();
                    } else {
                        ODD_COND.await();
                    }
                } catch (InterruptedException e) {
                    break;
                } finally {
                    LOCK.unlock();
                }
            }
            EVEN_COND.signal();
        }, "基数线程B").start();
    }
}

方式1和方式2存在的问题

1、线程先要获得并持有锁,必须在锁块(synchronized或lock)中,必须配合使用

2、必须要先等待后唤醒,线程才能够被唤醒

LockSupport主要是解决上面2个问题,LockSupport 类使用了一种名为 permit(许可)的概念来做到阻塞和唤醒线程的功能,每个线程都有一个许可(permit),permit 只有两个值 1 和零,默认是零,不能累积

到此这篇关于Java三大线程同步机制代码实战指南的文章就介绍到这了,更多相关java线程同步机制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • springboot责任链模式实现多级校验

    springboot责任链模式实现多级校验

    责任链模式是将链中的每一个节点看作是一个对象,每个节点处理的请求不同,且内部自动维护一个下一节点对象,下面我们来聊聊springboot如何利用责任链模式实现多级校验吧
    2024-11-11
  • Java代理模式之静态代理与动态代理详解

    Java代理模式之静态代理与动态代理详解

    Java代理分为静态代理和动态代理,静态代理需手动编写代理类,适合少量对象,动态代理运行时自动生成代理类,适用于大量对象,如Spring AOP,这篇文章主要介绍了Java代理模式之静态代理与动态代理的相关资料,需要的朋友可以参考下
    2026-01-01
  • Spring Boot 3 RestClient使用实战案例

    Spring Boot 3 RestClient使用实战案例

    本文详细介绍了SpringBoot3中RestClient的使用方法,从基础到高级,涵盖了各种常见场景和最佳实践,通过本教程,读者可以理解RestClient的核心概念和优势,感兴趣的朋友跟随小编一起看看吧
    2026-01-01
  • java springmvc 注册中央调度器代码解析

    java springmvc 注册中央调度器代码解析

    这篇文章主要介绍了java springmvc 注册中央调度器代码解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-08-08
  • java的nio的使用示例分享

    java的nio的使用示例分享

    这篇教程展示了5个在Java编程的一些常见场景里使用NIO和NIO.2包的简单示例,需要的朋友可以参考下
    2014-03-03
  • java逐行读取文件(读取文件每一行、按行读取文件)附带详细代码

    java逐行读取文件(读取文件每一行、按行读取文件)附带详细代码

    这篇文章主要给大家介绍了关于java逐行读取文件(读取文件每一行、按行读取文件)的相关资料,读取文件是我们在日常工作中经常遇到的一个需求,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-09-09
  • JavaSE递归求解汉诺塔问题的思路与方法

    JavaSE递归求解汉诺塔问题的思路与方法

    递归是一种非常重要的算法思想,无论你是前端开发,还是后端开发,都需要掌握它,下面这篇文章主要给给大家介绍了关于JavaSE递归求解汉诺塔问题的思路与方法,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-08-08
  • 解决idea找不到setting.xml文件的问题

    解决idea找不到setting.xml文件的问题

    这篇文章主要介绍了解决idea找不到setting.xml文件的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02
  • 使用Java和SpringBoot实现服务器发送事件(Server-Sent Events)

    使用Java和SpringBoot实现服务器发送事件(Server-Sent Events)

    使用Java开发web应用,大多数时候我们提供的接口返回数据都是一次性完整返回,有些时候,我们也需要提供流式接口持续写出数据,以下提供一种简单的方式,本文给大家介绍了如何在Java web中实现服务器发送事件,需要的朋友可以参考下
    2024-02-02

最新评论