精华内容
下载资源
问答
  • 什么是线程阻塞?为什么会出现线程阻塞

    万次阅读 多人点赞 2019-02-14 22:20:01
    什么是线程阻塞? 在某一时刻某一个线程在运行一段代码的时候,这时候另一个线程也需要运行,但是在运行过程中的那个线程执行完成之前,另一个线程是无法获取到CPU执行权的(调用sleep方法是进入到睡眠暂停状态,...

    什么是线程阻塞?

    在某一时刻某一个线程在运行一段代码的时候,这时候另一个线程也需要运行,但是在运行过程中的那个线程执行完成之前,另一个线程是无法获取到CPU执行权的(调用sleep方法是进入到睡眠暂停状态,但是CPU执行权并没有交出去,而调用wait方法则是将CPU执行权交给另一个线程),这个时候就会造成线程阻塞。

    为什么会出现线程阻塞?

    1.睡眠状态:当一个线程执行代码的时候调用了sleep方法后,线程处于睡眠状态,需要设置一个睡眠时间,此时有其他线程需要执行时就会造成线程阻塞,而且sleep方法被调用之后,线程不会释放锁对象,也就是说锁还在该线程手里,CPU执行权还在自己手里,等睡眠时间一过,该线程就会进入就绪状态,典型的“占着茅坑不拉屎”;

    2.等待状态:当一个线程正在运行时,调用了wait方法,此时该线程需要交出CPU执行权,也就是将锁释放出去,交给另一个线程,该线程进入等待状态,但与睡眠状态不一样的是,进入等待状态的线程不需要设置睡眠时间,但是需要执行notify方法或者notifyall方法来对其唤醒,自己是不会主动醒来的,等被唤醒之后,该线程也会进入就绪状态,但是进入仅需状态的该线程手里是没有执行权的,也就是没有锁,而睡眠状态的线程一旦苏醒,进入就绪状态时是自己还拿着锁的。等待状态的线程苏醒后,就是典型的“物是人非,大权旁落“;

    3.礼让状态:当一个线程正在运行时,调用了yield方法之后,该线程会将执行权礼让给同等级的线程或者比它高一级的线程优先执行,此时该线程有可能只执行了一部分而此时把执行权礼让给了其他线程,这个时候也会进入阻塞状态,但是该线程会随时可能又被分配到执行权,这就很”中国化的线程“了,比较讲究谦让;

    4.自闭状态:当一个线程正在运行时,调用了一个join方法,此时该线程会进入阻塞状态,另一个线程会运行,直到运行结束后,原线程才会进入就绪状态。这个比较像是”走后门“,本来该先把你的事情解决完了再解决后边的人的事情,但是这时候有走后门的人,那就会停止给你解决,而优先把走后门的人事情解决了;

    5.suspend() 和 resume() :这两个方法是配套使用的,suspend() 是让线程进入阻塞状态,它的解药就是resume(),没有resume()它自己是不会恢复的,由于这种比较容易出现死锁现象,所以jdk1.5之后就已经被废除了,这对就是相爱相杀的一对。

    展开全文
  • wait线程阻塞

    千次阅读 2018-09-16 19:12:40
    线程阻塞通常是指一个线程在执行过程中由于某种原因从运行状态转为暂停状态的过程,线程阻塞会放弃CPU的使用权, 并且等待某个条件重新从暂停状态改为就绪状态。在Java中,通常使用object.wait让线程进入阻塞状态。 ...

    介绍

    线程阻塞通常是指一个线程在执行过程中由于某种原因从运行状态转为暂停状态的过程,线程阻塞会放弃CPU的使用权, 并且等待某个条件重新从暂停状态改为就绪状态。在Java中,通常使用object.wait让线程进入阻塞状态。

    使用

    首先我们先看wait方法,wait方法总共有三个重载方法,分别是 wait() wait(long timeout) wait(long timeout, int nanos),其中wait方法内部是调用了wait(0),顾名思义timeout就是超时时间,那么timeout等于0是什么意思呢,查看官方API如下:
    这里写图片描述
    意思就是如果timeout是0,不需考虑超时时间,即线程会无限等待直到被唤醒。
    下面写一个demo,代码如下:

        public static void main(String args[]) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println( "执行线程中");
                }
            });
            thread.setName("MyThread");
            thread.start();
            
            try{
                thread.wait();
            }catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(thread.getName() + "已经执行结束");
        }
    

    预想的输出结果应该是

    执行线程中
    MyThread已经执行结束
    

    实际上报错了

    Exception in thread "main" java.lang.IllegalMonitorStateException
    

    查看wait的API介绍有这么一句标注 The current thread must own this object’s monitor.,大意就是执行wait方法的线程必须持有线程的对象锁,使用synchronized对thread对象加锁既可,代码如下:

            try{
                synchronized (thread) {
                    thread.wait();
                }
            }catch (InterruptedException e) {
                e.printStackTrace();
            }
    

    这样一来,通过synchronize既可获取线程的对象锁,就可以达到阻塞线程的作用了,有人可能会疑惑说为什么没有调用notify方法,这是因为当线程死亡之后,相应的wait方法也会失效。

    当然对于线程的阻塞,通用使用线程的join方法,代码如下:

        public static void main(String args[]) {
            Thread thread1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println( "执行线程1中");
                }
            });
            thread1.setName("MyThread -- 1");
            thread1.start();
    
            Thread thread2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println( "执行线程2中");
                }
            });
            thread2.setName("MyThread -- 2");
            thread2.start();
    
            try{
                thread1.join();
                thread2.join();
            }catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(thread1.getName() + " " + thread2.getName()  + "  已经执行结束");
        }
    

    通过调用join方法,就可以让线程阻塞,我们看一下join的方法实现:

        public final synchronized void join(long var1) throws InterruptedException {
            long var3 = System.currentTimeMillis();
            long var5 = 0L;
            if (var1 < 0L) {
                throw new IllegalArgumentException("timeout value is negative");
            } else {
                if (var1 == 0L) {
                    while(this.isAlive()) {
                        this.wait(0L);
                    }
                } else {
                    while(this.isAlive()) {
                        long var7 = var1 - var5;
                        if (var7 <= 0L) {
                            break;
                        }
    
                        this.wait(var7);
                        var5 = System.currentTimeMillis() - var3;
                    }
                }
    
            }
        }
    

    其实就是当线程还存活时,调用wait方法。需要注意的是,join方法是synchronize的,因为需要获取对象锁。

    参考

    Wait方法的官方API介绍

    展开全文
  • * 单线程/多线程阻塞I/O模型 * 单线程非阻塞I/O模型 * 多线程非阻塞I/O模型,Reactor及其改进 前言 这里探讨的服务器模型主要指的是服务器端对I/O的处理模型。从不同维度可以有不同的分类,这里从I/O的阻塞与...

    前言的前言

    服务器模型涉及到线程模式和IO模式,搞清楚这些就能针对各种场景有的放矢。该系列分成三部分:
    * 单线程/多线程阻塞I/O模型
    * 单线程非阻塞I/O模型
    * 多线程非阻塞I/O模型,Reactor及其改进

    前言

    这里探讨的服务器模型主要指的是服务器端对I/O的处理模型。从不同维度可以有不同的分类,这里从I/O的阻塞与非阻塞、I/O处理的单线程与多线程角度探讨服务器模型。

    对于I/O,可以分成阻塞I/O与非阻塞I/O两大类型。阻塞I/O在做I/O读写操作时会使当前线程进入阻塞状态,而非阻塞I/O则不进入阻塞状态。

    对于线程,单线程情况下由一条线程负责所有客户端连接的I/O操作,而多线程情况下则由若干线程共同处理所有客户端连接的I/O操作。

    单线程非阻塞I/O模型

    多线程阻塞I/O模型通过引入多线程确实提高了服务器端的并发处理能力,但每个连接都需要一个线程负责I/O操作。当连接数量较多时可能导致机器线程数量太多,而这些线程大多数时间却处于等待状态,造成极大的资源浪费。鉴于多线程阻塞I/O模型的缺点,有没有可能用一个线程就可以维护多个客户端连接并且不会阻塞在读写操作呢?下面介绍单线程非阻塞I/O模型。

    单线程非阻塞I/O模型最重要的一个特点是,在调用读取或写入接口后立即返回,而不会进入阻塞状态。在探讨单线程非阻塞I/O模型前必须要先了解非阻塞情况下套接字事件的检测机制,因为对于单线程非阻塞模型最重要的事情是检测哪些连接有感兴趣的事件发生。一般会有如下三种检测方式。

    应用程序遍历套接字的事件检测

    当多个客户端向服务器请求时,服务器端会保存一个套接字连接列表中,应用层线程对套接字列表轮询尝试读取或写入。对于读取操作,如果成功读取到若干数据,则对读取到的数据进行处理;如果读取失败,则下一个循环再继续尝试。对于写入操作,先尝试将数据写入指定的某个套接字,写入失败则下一个循环再继续尝试。

    这里写图片描述

    这样看来,不管有多少个套接字连接,它们都可以被一个线程管理,一个线程负责遍历这些套接字列表,不断地尝试读取或写入数据。这很好地利用了阻塞的时间,处理能力得到提升。但这种模型需要在应用程序中遍历所有的套接字列表,同时需要处理数据的拼接,连接空闲时可能也会占用较多CPU资源,不适合实际使用。对此改进的方法是使用事件驱动的非阻塞方式。

    内核遍历套接字的事件检测

    这种方式将套接字的遍历工作交给了操作系统内核,把对套接字遍历的结果组织成一系列的事件列表并返回应用层处理。对于应用层,它们需要处理的对象就是这些事件,这就是其中一种事件驱动的非阻塞方式的实现。

    服务器端有多个客户端连接,应用层向内核请求读写事件列表。内核遍历所有套接字并生成对应的可读列表readList和可写列表writeList。readList标明了每个套接字是否可读,例如套接字1的值为1,表示可读,socket2的值为0,表示不可读。writeList则标明了每个套接字是否可写。应用层遍历读写事件列表readList和writeList,做相应的读写操作。

    这里写图片描述

    内核遍历套接字时已经不用在应用层对所有套接字进行遍历,将遍历工作下移到内核层,这种方式有助于提高检测效率。然而,它需要将所有连接的可读事件列表和可写事件列表传到应用层,假如套接字连接数量变大,列表从内核复制到应用层也是不小的开销。另外,当活跃连接较少时,内核与应用层之间存在很多无效的数据副本,因为它将活跃和不活跃的连接状态都复制到应用层中。

    内核基于回调的事件检测

    通过遍历的方式检测套接字是否可读可写是一种效率比较低的方式,不管是在应用层中遍历还是在内核中遍历。所以需要另外一种机制来优化遍历的方式,那就是回调函数。内核中的套接字都对应一个回调函数,当客户端往套接字发送数据时,内核从网卡接收数据后就会调用回调函数,在回调函数中维护事件列表,应用层获取此事件列表即可得到所有感兴趣的事件。

    内核基于回调的事件检测方式有两种。第一种是用可读列表readList和可写列表writeList标记读写事件,套接字的数量与readList和writeList两个列表的长度一样,readList第一个元素标为1则表示套接字1可读,同理,writeList第二个元素标为1则表示套接字2可写。如图所示,多个客户端连接服务器端,当客户端发送数据过来时,内核从网卡复制数据成功后调用回调函数将readList第一个元素置为1,应用层发送请求读、写事件列表,返回内核包含了事件标识的readList和writeList事件列表,进而分表遍历读事件列表readList和写事件列表writeList,对置为1的元素对应的套接字进行读或写操作。这样就避免了遍历套接字的操作,但仍然有大量无用的数据(状态为0的元素)从内核复制到应用层中。于是就有了第二种事件检测方式。

    这里写图片描述

    内核基于回调的事件检测方式二如图所示。服务器端有多个客户端套接字连接。首先,应用层告诉内核每个套接字感兴趣的事件。接着,当客户端发送数据过来时,对应会有一个回调函数,内核从网卡复制数据成功后即调回调函数将套接字1作为可读事件event1加入到事件列表。同样地,内核发现网卡可写时就将套接字2作为可写事件event2添加到事件列表中。最后,应用层向内核请求读、写事件列表,内核将包含了event1和event2的事件列表返回应用层,应用层通过遍历事件列表得知套接字1有数据待读取,于是进行读操作,而套接字2则可以写入数据。

    这里写图片描述

    上面两种方式由操作系统内核维护客户端的所有连接并通过回调函数不断更新事件列表,而应用层线程只要遍历这些事件列表即可知道可读取或可写入的连接,进而对这些连接进行读写操作,极大提高了检测效率,自然处理能力也更强。

    对于Java来说,非阻塞I/O的实现完全是基于操作系统内核的非阻塞I/O,它将操作系统的非阻塞I/O的差异屏蔽并提供统一的API,让我们不必关心操作系统。JDK会帮我们选择非阻塞I/O的实现方式,例如对于Linux系统,在支持epoll的情况下JDK会优先选择用epoll实现Java的非阻塞I/O。这种非阻塞方式的事件检测机制就是效率最高的“内核基于回调的事件检测”中的第二种方式。

    在了解了非阻塞模式下的事件检测方式后,重新回到对单线程非阻塞I/O模型的讨论。虽然只有一个线程,但是它通过把非阻塞读写操作与上面几种检测机制配合就可以实现对多个连接的及时处理,而不会因为某个连接的阻塞操作导致其他连接无法处理。在客户端连接大多数都保持活跃的情况下,这个线程会一直循环处理这些连接,它很好地利用了阻塞的时间,大大提高了这个线程的执行效率。

    单线程非阻塞I/O模型的主要优势体现在对多个连接的管理,一般在同时需要处理多个连接的发场景中会使用非阻塞NIO模式,此模型下只通过一个线程去维护和处理连接,这样大大提高了机器的效率。一般服务器端才会使用NIO模式,而对于客户端,出于方便及习惯,可使用阻塞模式的套接字进行通信。

    =============广告时间===============

    公众号的菜单已分为“分布式”、“机器学习”、“深度学习”、“NLP”、“Java深度”、“Java并发核心”、“JDK源码”、“Tomcat内核”等,可能有一款适合你的胃口。

    鄙人的新书《Tomcat内核设计剖析》已经在京东销售了,有需要的朋友可以购买。感谢各位朋友。

    为什么写《Tomcat内核设计剖析》

    =========================

    欢迎关注:

    这里写图片描述

    展开全文
  • * 单线程/多线程阻塞I/O模型 * 单线程非阻塞I/O模型 * 多线程非阻塞I/O模型,Reactor及其改进 前言 这里探讨的服务器模型主要指的是服务器端对I/O的处理模型。从不同维度可以有不同的分类,这里从I/O的阻塞与...

    前言的前言

    服务器模型涉及到线程模式和IO模式,搞清楚这些就能针对各种场景有的放矢。该系列分成三部分:
    * 单线程/多线程阻塞I/O模型
    * 单线程非阻塞I/O模型
    * 多线程非阻塞I/O模型,Reactor及其改进

    前言

    这里探讨的服务器模型主要指的是服务器端对I/O的处理模型。从不同维度可以有不同的分类,这里从I/O的阻塞与非阻塞、I/O处理的单线程与多线程角度探讨服务器模型。

    对于I/O,可以分成阻塞I/O与非阻塞I/O两大类型。阻塞I/O在做I/O读写操作时会使当前线程进入阻塞状态,而非阻塞I/O则不进入阻塞状态。

    对于线程,单线程情况下由一条线程负责所有客户端连接的I/O操作,而多线程情况下则由若干线程共同处理所有客户端连接的I/O操作。

    多线程非阻塞I/O模型

    单线程非阻塞I/O模型已经大大提高了机器的效率,而在多核的机器上可以通过多线程继续提高机器效率。最朴实、最自然的做法就是将客户端连接按组分配给若干线程,每个线程负责处理对应组内的连接。如图所示,有4个客户端访问服务器,服务器将套接字1和套接字2交由线程1管理,而线程2则管理套接字3和套接字4,通过事件检测及非阻塞读写就可以让每个线程都能高效处理。

    这里写图片描述

    最经典的多线程非阻塞I/O模型方式是Reactor模式。首先看单线程下的Reactor,Reactor将服务器端的整个处理过程分成若干个事件,例如分为接收事件、读事件、写事件、执行事件等。Reactor通过事件检测机制将这些事件分发给不同处理器去处理。如图所示,若干客户端连接访问服务器端,Reactor负责检测各种事件并分发到处理器,这些处理器包括接收连接的accept处理器、读数据的read处理器、写数据的write处理器以及执行逻辑的process处理器。在整个过程中只要有待处理的事件存在,即可以让Reactor线程不断往下执行,而不会阻塞在某处,所以处理效率很高。

    基于单线程Reactor模型,根据实际使用场景,把它改进成多线程模式。常见的有两种方式:一种是在耗时的process处理器中引入多线程,如使用线程池;另一种是直接使用多个Reactor实例,每个Reactor实例对应一个线程。

    这里写图片描述

    Reactor模式的一种改进方式如图所示。其整体结构基本上与单线程的Reactor类似,只是引入了一个线程池。由于对连接的接收、对数据的读取和对数据的写入等操作基本上都耗时较少,因此把它们都放到Reactor线程中处理。然而,对于逻辑处理可能比较耗时的工作,可以在process处理器中引入线程池,process处理器自己不执行任务,而是交给线程池,从而在Reactor线程中避免了耗时的操作。将耗时的操作转移到线程池中后,尽管Reactor只有一个线程,它也能保证Reactor的高效。

    这里写图片描述

    Reactor模式的另一种改进方式如图所示。其中有多个Reactor实例,每个Reactor实例对应一个线程。因为接收事件是相对于服务器端而言的,所以客户端的连接接收工作统一由一个accept处理器负责,accept处理器会将接收的客户端连接均匀分配给所有Reactor实例,每个Reactor实例负责处理分配到该Reactor上的客户端连接,包括连接的读数据、写数据和逻辑处理。这就是多Reactor实例的原理。

    多线程非阻塞I/O模式让服务器端处理能力得到很大提高,它充分利用机器的CPU,适合用于处理高并发的场景,但它也让程序更复杂,更容易出现问题。

    这里写图片描述

    =============广告时间===============

    公众号的菜单已分为“分布式”、“机器学习”、“深度学习”、“NLP”、“Java深度”、“Java并发核心”、“JDK源码”、“Tomcat内核”等,可能有一款适合你的胃口。

    鄙人的新书《Tomcat内核设计剖析》已经在京东销售了,有需要的朋友可以购买。感谢各位朋友。

    为什么写《Tomcat内核设计剖析》

    =========================

    欢迎关注:

    这里写图片描述

    展开全文
  • * 单线程/多线程阻塞I/O模型 * 单线程非阻塞I/O模型 * 多线程非阻塞I/O模型,Reactor及其改进前言这里探讨的服务器模型主要指的是服务器端对I/O的处理模型。从不同维度可以有不同的分类,这里从I/O的阻塞与非阻塞...
  • Python2:线程挂起和线程阻塞 本文参考博客什么是线程阻塞?为什么会出现线程阻塞?、线程和进程/阻塞和挂起。 (1)线程挂起: ①线程挂起简介: 线程挂起操作实际上就是线程进入非可执行状态下,在这个状态下...
  • 线程阻塞机制

    2019-04-19 12:03:50
    一、为什么引入线程阻塞机制 为了解决对共享存储区的访问冲突,Java 引入了同步机制,现在让我们来考察多个线程对共享资源的访问,显然同步机制已经不够了,因为在任意时刻所要求的资源不一定已经准备好了被访问,...
  • Java线程状态、线程停止、线程阻塞

    千次阅读 2015-05-28 08:59:44
    Java线程状态、线程停止、线程阻塞
  • 自己调试程序是可以执行,但是不调试运行,有写方法不走,是因为线程阻塞了吗,怎么解决线程阻塞
  • 阻塞指的是暂停一个线程的执行以等待某个条件发生(如某资源就绪),学过操作系统的同学对它一定已经很熟悉了。Java 提供了大量方法来支持阻塞,下面让我们逐一分析。方法说明sleep() sleep() 允许 指定以毫秒为单位的...
  • java线程阻塞

    2013-03-22 21:54:05
    线程阻塞是指一个线程的执行,在等待某个条件或者资源,在java中提供了很多方法来支持线程阻塞。 ( 这里我先提一下,线程的阻塞是会让出cpu的!,在最后有简单的解释) 下面我逐一分析。  1. sleep() 方法:...
  • 什么导致线程阻塞

    千次阅读 2019-07-25 13:07:14
    导致线程阻塞的原因主要有以下几方面。 1、线程进行了休眠:线程执行了Thread.sleep(int n)方法,线程放弃CPU,睡眠n毫秒,然后恢复运行。 2、线程等待获取同步锁才能进行下一步操作:线程要执行一段同步代码,由于...
  • UI线程阻塞以及优化

    千次阅读 2017-10-13 16:28:35
    =)这是因为线程的阻塞引起的,在这里我讲述一下UI线程,一般处理程序会在UI线程中执行耗时操作,这回导致UI线程阻塞,当UI线程阻塞,屏幕会出现卡死,用户体验会变得非常差,当线程阻塞超过5s,android系统可能进行...
  • java线程阻塞问题排查方法

    千次阅读 2019-04-17 16:55:38
    java线程阻塞问题排查方法
  • 线程阻塞,单例模式

    千次阅读 2018-04-23 21:34:03
    以前自己理解不到位,单例模式下,只存在一个实例对象,那么在高并发的情况下,... 线程阻塞发生在多个线程访问需要等待的资源的情形下,阻塞和是否是单例,多例是没有关系的。  单例多线程  现在对这个问题有...
  • 线程阻塞与唤醒

    千次阅读 2017-07-17 16:44:20
    线程阻塞与唤醒的方法如图: package newThread;import java.util.Scanner;public class Twothread implements Runnable { private int i; @Override public void run() { //run方法同样是线程执行体 for(;i...
  • 线程阻塞类型

    2017-08-13 12:35:33
    java 多线程阻塞的类型(参照java in thinking) 1)调用sleep(millsseconds)进入休眠状态, 在指定时间不会运行。 2)该对象.调用wait()使线程挂起,直到线程得到notify()或者notifyAll()消息会使...
  • Java线程阻塞与中断

    千次阅读 2016-11-01 08:59:52
    线程阻塞和中断 1、线程阻塞 一个线程进入阻塞状态可能的原因: ①通过调用sleep(millseconds)使任务进入休眠状态; class Demo1 implements Runnable throws InterruptedException{  public void ...
  • 线程并发学习—-线程阻塞(sleep、wait、notifyAll、notify) 线程并发学习—-线程阻塞(synchronized) 线程并发学习—-线程阻塞(lock) 线程并发学习—-Thread、Runnable、Callable spring学习—-线程池 Lock...
  • Java线程阻塞方法sleep()和wait()精炼详解

    万次阅读 多人点赞 2018-04-10 22:53:58
    感兴趣的读者可以参见笔者之前的文章《Java中什么方法导致线程阻塞》,里面详细讲述了为什么Java要造成线程阻塞和Java中造成线程阻塞的几种方法。 线程的生命周期 这是笔者在谷歌图片中找到的一张简单描述线程...
  • 线程并发学习—-线程阻塞(sleep、wait、notifyAll、notify) 线程并发学习—-线程阻塞(synchronized) 线程并发学习—-线程阻塞(concurrent包) 线程并发学习—-Thread、Runnable、Callable spring学习—-...
  • 线程阻塞的原因

    千次阅读 2014-03-23 23:21:30
    线程阻塞的原因 导致线程阻塞的原因主要由以下几方面。 1、线程执行了Thread.sleep(int n)方法,线程放弃CPU,睡眠n毫秒,然后恢复运行。 2、线程要执行一段同步代码,由于无法获得相关的同步锁,只好进入...
  • 假设有多个线程阻塞等待一个信号量,其间有某个线程异常挂掉了,阻塞队列中排在该线程后面的线程还能正常获取到信号量吗?
  • reactor线程阻塞引起故障

    千次阅读 2016-07-28 16:47:22
    jstack打印JVM堆栈,可以看到reactor线程阻塞了,导致它对应的前端连接无法使用。阻塞在了oracle驱动rollback动作,这里其实是因为oracle驱动为了保证串行请求响应而在底层加了锁,而这个通道被慢语句塞住了,所以...
  • Java线程阻塞的概念

    千次阅读 2014-01-20 22:48:33
    线程阻塞的原因 导致线程阻塞的原因主要由以下几方面。 1、线程执行了Thread.sleep(int n)方法,线程放弃CPU,睡眠n毫秒,然后恢复运行。 2、线程要执行一段同步代码,由于无法获得相关的同步锁,只好进入阻塞状态,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 58,097
精华内容 23,238
关键字:

线程阻塞