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线程同步机制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot2.x配置多数据源方式

    SpringBoot2.x配置多数据源方式

    这篇文章主要介绍了SpringBoot2.x配置多数据源方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • 详解MyBatis-Plus Wrapper条件构造器查询大全

    详解MyBatis-Plus Wrapper条件构造器查询大全

    这篇文章主要介绍了详解MyBatis-Plus Wrapper条件构造器查询大全,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • SpringBoot中使用@Async实现异步任务调用详解

    SpringBoot中使用@Async实现异步任务调用详解

    这篇文章主要介绍了SpringBoot中使用@Async实现异步任务调用详解,一个可以无需等待被调用函数的返回值就让操作继续进行的方法(来自百度百科),即程序在顺序执行时,不等待异步调用的语句返回结果就执行后面的程序,需要的朋友可以参考下
    2023-12-12
  • java实现通讯录管理系统

    java实现通讯录管理系统

    这篇文章主要为大家详细介绍了java实现通讯录管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-07-07
  • Java的异常体系以及File类构造方法详解

    Java的异常体系以及File类构造方法详解

    这篇文章主要为大家介绍了Java的异常体系以及File类构造方法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05
  • springboot配置mysql数据库spring.datasource.url报错的解决

    springboot配置mysql数据库spring.datasource.url报错的解决

    这篇文章主要介绍了springboot配置mysql数据库spring.datasource.url报错的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • MyBatis-Plus 全面介绍与Spring Boot 集成最佳实践

    MyBatis-Plus 全面介绍与Spring Boot 集成最佳实践

    MyBatis-Plus是MyBatis的增强工具,提供了通用CRUD、分页、条件构造器等功能,简化了开发,减少重复SQL编写,它支持多种主键生成策略,内置乐观锁和逻辑删除,且兼容MyBatis原有代码,本文介绍MyBatis-Plus全面介绍与Spring Boot 集成最佳实践,感兴趣的朋友一起看看吧
    2025-12-12
  • Java输入字母来判断星期几的实现代码

    Java输入字母来判断星期几的实现代码

    这篇文章主要介绍了Java输入字母来判断星期几的实现代码,用情况语句比较好,如果第一个字母一样,则判断用情况语句或if语句判断第二个字母需要的朋友可以参考下
    2017-02-02
  • java工厂实例BeanFactoryPostProcessor和BeanPostProcessor区别分析

    java工厂实例BeanFactoryPostProcessor和BeanPostProcessor区别分析

    这篇文章主要为大家介绍了BeanFactoryPostProcessor和BeanPostProcessor区别示例分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • Spring AOP中的JDK和CGLib动态代理哪个效率更高?

    Spring AOP中的JDK和CGLib动态代理哪个效率更高?

    今天小编就为大家分享一篇关于Spring AOP中的JDK和CGLib动态代理哪个效率更高?,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03

最新评论