浅谈new Runnable(){}--new Interface(){}

   在java多线程中实现多线程的方式有两种①extends Thread ②implements Runnable。这两种情况是我们最常见的,还有一种是由第二种变形而来的直接new Runnable(){},我写这篇博客的目的是来将new Runnable(){}中的机制理一理,让读者更清晰地理解new Runnable(){},下面我就通过代码来将问题演示。
package com.cph.Thread;

public class Text2 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
         Runnable runnable=new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                System.out.println("i am new Runnable(){xxx}");

            }
        };
        Thread thread=new Thread(runnable);
        thread.start();
    }

}
    这段代码不会出现什么问题,控制台会输出:i am new Runnable(){xxx}
    但如果java基础扎实一点的朋友,就会疑问Runnable()是接口,我们都知道java的接口是不可以实例化的,但代码中的new Runnable(){xxx}确是实例化了,为什么?
    接口和抽象类不可以实例化是对的,这个是java语法规范来的,**而new Runnable(){}其实不是实例化Runnable接口来的,实际上一种内部类的一种简写**
    在这里:
    ①首先构造了一个”implements Runnable “的无名local内部类(方法内的内部类) 
    ②然后构造了这个无名local内部类的一个实例 
    ③然后用Runnable来表示这个无名local内部类的type(OO多态)。
    例如上面这段代码编译后你会看到其实是编译了两个类来的,如下:

这里写图片描述

    其中Text2$1就是无名local内部内类,这个也就很好地解释了为什么在main()方法中new Runnable(){xxx}里面的调用main()方法中的变量的时候要用final关键字来修饰。
    上面只是借助new Runnable(){xxx}特例来说明接口在方法中new的机制,对其他接口同理可得。
<think>我们正在讨论Java多线程中线程状态转换的具体情况。根据用户的问题,需要详细解释以下几种状态转换: 1. NEWRUNNABLE 2. RUNNABLE 到 BLOCKED 3. RUNNABLE 到 WAITING 4. RUNNABLE 到 TIMED_WAITING 5. RUNNABLE 到 TERMINATED 我们将结合引用中的信息,尤其是引用[1][2][3][4][5]中关于线程状态的说明,来详细描述这些转换发生的原因和条件。 注意:在Java中,线程状态由`Thread.State`枚举定义,包括:NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED。 下面逐一分析: </think>### Java多线程线程状态转换详解 根据问题要求,结合引用内容,详细说明Java线程状态转换的场景和原因: #### 1. **NEWRUNNABLE** - **触发条件**:调用线程的`start()`方法 - **转换原理**: 线程对象创建后处于NEW状态(未启动)。调用`start()`会向操作系统申请线程资源,当操作系统调度器分配CPU时间片后,线程进入RUNNABLE状态[^1][^2]。 - **关键点**: - RUNNABLE包含操作系统级的**就绪(Ready)** 和 **运行中(Running)** 状态[^3][^5] - 直接调用`run()`方法不会触发状态转换(仍在原线程执行) #### 2. **RUNNABLE → BLOCKED** - **触发条件**:竞争`synchronized`锁失败 - **转换原理**: 当线程尝试进入`synchronized`代码块/方法时,若监视器锁已被其他线程持有,则进入BLOCKED状态[^1][^3]。此时线程位于**同步队列**等待锁释放。 - **典型场景**: ```java synchronized(lock) { // 若锁被占用,竞争线程进入BLOCKED // 临界区代码 } ``` - **退出条件**:持有锁的线程退出同步块,系统唤醒一个BLOCKED线程[^4] #### 3. **RUNNABLE → WAITING** - **触发条件**:执行以下无超时方法 - `Object.wait()` - `Thread.join()`(无参) - `LockSupport.park()` - **转换原理**: 线程主动放弃CPU执行权,进入**无限期等待**状态,释放持有的锁资源[^1][^3]。需其他线程通过`notify()/notifyAll()`唤醒。 - **示例**: ```java synchronized(lock) { lock.wait(); // 调用后线程进入WAITING } ``` #### 4. **RUNNABLE → TIMED_WAITING** - **触发条件**:执行以下带超时参数的方法 - `Thread.sleep(long millis)` - `Object.wait(long timeout)` - `Thread.join(long millis)` - `LockSupport.parkNanos()` - **转换原理**: 与WAITING类似,但设置最大等待时间。时间耗尽或提前被唤醒时,线程返回RUNNABLE状态[^1][^4]。 - **特点**: - 无需外部唤醒即可自动恢复(相比WAITING) - 常用于轮询任务和超时控制 #### 5. **RUNNABLE → TERMINATED** - **触发条件**: - 线程`run()`方法执行完毕 - 线程抛出未捕获异常终止 - 调用`Thread.stop()`(已废弃) - **终止过程**: 1. 操作系统回收线程资源 2. JVM移除线程对象引用 3. 状态固定为TERMINATED不可逆[^1][^5] - **关键点**: - 终止后调用`start()`会抛出`IllegalThreadStateException` ### 状态转换流程图 ```mermaid graph LR A[NEW] -->|start()| B(RUNNABLE) B -->|synchronized竞争失败| C[BLOCKED] B -->|wait()/join()| D[WAITING] B -->|sleep()/wait(time)| E[TIMED_WAITING] B -->|run()结束/异常| F[TERMINATED] C -->|获取锁成功| B D -->|notify()/notifyAll()| B E -->|超时/唤醒| B ``` > 注:RUNNABLE到BLOCKED仅在竞争`synchronized`锁时发生,使用`ReentrantLock`竞争失败会进入WAITING队列(AQS机制) --- ### 相关问题 1. 为什么Java要将操作系统的Ready和Running状态统一为RUNNABLE? 2. `WAITING`和`TIMED_WAITING`状态在JVM内部实现上有何区别? 3. 如何诊断线程长时间处于`BLOCKED`状态的问题? 4. 调用`Thread.yield()`会导致线程状态变化吗?为什么? 5. 守护线程(`Daemon`)的状态转换与用户线程有何不同? 6. Java虚拟线程(Loom项目)的状态机与传统线程有何差异? > 引用说明: > [^1] Java线程的6种状态定义及说明 > [^2] Java线程状态与操作系统线程状态的关系 > [^3] WAITING/TIMED_WAITING状态触发条件 > [^4] 线程状态转换的代码验证 > [^5] RUNNABLE状态包含Ready和Running子状态
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值