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

    万次阅读 多人点赞 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介绍

    展开全文
  • 线程阻塞方式:  1、join 2、sleep 3、yield 4、改变线程的优先级 5、将线程设置成守护线程(jvm中的垃圾回收线程) 参考:https://blog.csdn.net/liyuchong2537631/article/details/51900198 ...

    线程阻塞方式:

      1、join
      2、sleep
      3、yield
      4、改变线程的优先级
      5、将线程设置成守护线程(jvm中的垃圾回收线程)

     

    参考:https://blog.csdn.net/liyuchong2537631/article/details/51900198

    展开全文
  • Java线程状态、线程停止、线程阻塞

    千次阅读 2015-05-28 08:59:44
    Java线程状态、线程停止、线程阻塞

    线程状态(五种状态)

    Java 线程的生命周期包括创建,就绪,运行,阻塞,死亡5 个状态。一个 Java 线程总是处于这 5 个生命周期状态之一,并在一定条件下可以在不同状态之间进行转换 。

    创建状态 (New Thread)
    在 Java 语言中使用 new操作符创建一个线程后,该线程仅仅是一个空对象,它具备了线程的一些特征,但此时系统没有为其分配资源,这时的线程处于创建状态。

    就绪状态 (Runnable)
    使用 start()方法启动一个线程后,系统为该线程分配了除 CPU 外的所需资源,使该线程处于就绪状态。此外,如果某个线程执行了 yield() 方法,那么该线程会被暂时剥夺 CPU 资源,重新进入就绪状态。

    运行状态 (Running)
    Java运行系统通过调度选中一个处于就绪状态的线程,使其占有 CPU 并转为运行状态。此时,系统真正执行线程的 run() 方法。

    阻塞状态 (Blocked)
    一个正在运行的线程因某些原因不能继续运行时,它就进入阻塞状态。
    这些原因包括:当执行了某个线程对象的suspend()、sleep()等阻塞类型的方法时,该线程对象会被置入一个阻塞集(Blocked Pool)内,等待被唤醒(执行 resume()方法)或是因为超时而时自动苏醒;
    当多个线程试图进入某个同步区域(synchronized)时,没能进入该同步区域的线程会被置入锁定集(Lock Pool),直到获得该同步区域的锁,进入就绪状态;
    当线程执行了某个对象的 wait() 方法时,线程会被置入该对象的等待集(Wait Pool)中,直到执行了该对象的 notify()方法,wait()/notify()方法的执行要求线程首先获取到该对象的锁。

    死亡状态 (Dead)
    线程在 run() 方法执行结束后进入死亡状态。此外,如果线程执行了 interrupt()stop() 方法,那么它也会以异常退出的方式进入死亡状态。

    停止线程(两种方式)

    1、自然终止:线程体正常执行完毕
    2、外部干涉

    1)线程类中 定义线程体使用的标识。
    2)线程体使用该标识。
    3)提供对外的方法,改变该标识。
    4) 外部根据条件调用该方法即可

    注意:避免使用Thread类自己提供的stop()(具有不安全性)、suspend()(具有固有的死锁现象)、resume() 等方法

    package Threadstate;
    
    /**
     * 停止线程
     * @author liguodong
     */
    public class Demo01 {
        public static void main(String[] args) {
            Study s = new Study();
            new Thread(s).start();//启动
            //外部干涉
            for(int i=0;i<100;i++)
            {
                if(50==i)//外部干涉(并不是非常准确,还要看CPU)
                {
                    s.stop();
                }
                System.out.println("main....-->"+i);
            }
        }   
    }
    
    class Study implements Runnable
    {
        //1、线程类中,定义线程体使用的标识
        private boolean flag = true;    
        @Override
        public void run() {
            //2、线程体使用该标识
            while(flag)
            {
                System.out.println("Study thread....");
            }       
        }
        //3、对外提供方法改变标识
        public void stop()
        {
            this.flag = false;
        }
    }

    线程阻塞

    1、join:合并线程
    2、yield:暂停自己的线程 static方法
    3、sleep:指定的毫秒数内让当前正在执行的线程休眠(暂停执行),不会释放锁。
    (1)与时间相关,如倒计时
    (2)模拟网络延时

    package Threadstate;
    
    /**
     * 线程阻塞: join合并线程   
     */
    public class Demo02 extends Thread{
    
        @Override
        public void run() {
            for(int i=0;i<100;i++)
            {
                    System.out.println("join..."+i);            
            }   
        }   
        public static void main(String[] args) throws InterruptedException {
    
            Demo02 demo = new Demo02();
            Thread t = new Thread(demo);//新生
            t.start();//就绪
            //cpu调度运行       
            for(int i=0;i<100;i++)
            {
                if(50==i)
                {
                    t.join();//main阻塞
                }
                System.out.println("main..."+i);                
            }
        }
    }
    
    package Threadstate;
    /**
     * yield:暂停自己的线程   static方法
     * @author liguodong
     */
    public class Demo03 extends Thread{
        public static void main(String[] args) {
            Demo03 demo = new Demo03(); 
            Thread t  = new Thread(demo);//新生
            t.start();//就绪
            //cpu调度运行       
            for(int i=0; i<1000; i++)
            {
                if(i%20==0)
                {
                    //在main线程中,暂停本线程main   
                    //本方法写在那个线程体里面就停止那个线程,如果在run里面暂停 Demo03。
                    Thread.yield();//静态方法(并没有严格意义上的暂停,可能CPU又调度到它)
                }
                System.out.println("main..."+i);
            }
    
        }   
        @Override
        public void run() {
            for(int i=0; i<1000; i++)
            {   
                System.out.println("yield..."+i);
            }
        }
    }
    package Threadstate;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    /**
     * sleep:指定的毫秒数内让当前正在执行的线程**休眠**(暂停执行),不会释放锁。
     * 倒计时
     * 1、倒数十个数,1秒内打印一个
     * 2、倒计时
     */
    public class Demo04 {
        public static void main(String[] args) throws InterruptedException
        {       
            //test01();
            test02();   
        }   
        //倒数十个数,1秒内打印一个
        public static void test01() throws InterruptedException
        {
            int num = 10;
            while(true)
            {
                System.out.println(num--);
                Thread.sleep(1000);//暂停
                if(num<=0)
                {
                    break;
                }
            }
        }
    
        //倒计时
        public static void test02() throws InterruptedException
        {
            //new Date()当前时间   System.currentTimeMillis()也表示当前时间
            Date endTime = new Date(System.currentTimeMillis()+10*1000);//当前时间往后10秒
            long end = endTime.getTime();//获取结束时间的长整型
            while(true)
            {
                //输出
                System.out.println(new SimpleDateFormat("HH:mm:ss").format(endTime));
                //构建下一秒的时间
                endTime = new Date(endTime.getTime()-1000);//减一秒  endTime依次递减
                //等待1秒
                Thread.sleep(1000);//暂停
                //10秒以内继续   否则退出 end-10000当前时间  
                if(end-10000>endTime.getTime())
                {
                    break;
                }
            }   
        }       
    }
    
    package Threadstate;
    
    /**
     * sleep模拟网络延时  线程不安全的类   结果可能不准确
     */
    public class Demo05 {
        public static void main(String[] args) {
            //真实角色
            Web12306 web = new Web12306();
            //代理
            Thread t1 = new Thread(web,"德玛西亚");
            Thread t2 = new Thread(web,"卡特琳娜");
            Thread t3 = new Thread(web,"德邦总管");
            //启动线程
            t1.start();
            t2.start();
            t3.start();
        }
    }
    
    class Web12306 implements Runnable{
        private int num = 50;
        @Override
        public void run() {
            while(true)
            {
                if(num<=0)
                {
                    break;//跳出循环
                }
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"抢到了倒数第"+num--+"张");            
            }
        }
    }
    展开全文
  • * 单线程/多线程阻塞I/O模型 * 单线程非阻塞I/O模型 * 多线程非阻塞I/O模型,Reactor及其改进 前言 这里探讨的服务器模型主要指的是服务器端对I/O的处理模型。从不同维度可以有不同的分类,这里从I/O的阻塞与...
  • java线程阻塞唤醒的四种方式

    万次阅读 2018-03-07 17:49:05
    java在多线程情况下,经常会使用到线程阻塞与唤醒,这里就为大家简单介绍一下以下几种阻塞/唤醒方式与区别,不做详细的介绍与代码分析 suspend与resume Java废弃 suspend() 去挂起线程的原因,是因为 suspend...
  • * 单线程/多线程阻塞I/O模型 * 单线程非阻塞I/O模型 * 多线程非阻塞I/O模型,Reactor及其改进前言这里探讨的服务器模型主要指的是服务器端对I/O的处理模型。从不同维度可以有不同的分类,这里从I/O的阻塞与非阻塞...
  • 线程阻塞的实现原理

    千次阅读 2018-10-13 13:54:06
    Java中,当多个线程同时请求独占锁时,JVM虚拟机会根据上一次获取锁操作中对锁的持有时间来决定是挂起线程还是让线程自旋,当上一次持有锁的时间相对较长时,会...常用的阻塞方式:加入FIFO的队列,或者while自旋。...
  • 1 查看阻塞根源线程的堆栈 2 ~95s 3 !clrstack
  • 线程阻塞的原因

    万次阅读 2014-03-23 23:21:30
    线程阻塞的原因 导致线程阻塞的原因主要由以下几方面。 1、线程执行了Thread.sleep(int n)方法,线程放弃CPU,睡眠n毫秒,然后恢复运行。 2、线程要执行一段同步代码,由于无法获得相关的同步锁,只好进入...
  • 多线程之Java线程阻塞与唤醒

    万次阅读 2014-12-06 18:58:01
    线程阻塞和唤醒在多线程并发过程中是一个关键点,当线程数量达到很大的数量级时,并发可能带来很多隐蔽的问题。如何正确暂停一个线程,暂停后又如何在一个要求的时间点恢复,这些都需要仔细考虑的细节。在Java发展...
  • * 单线程/多线程阻塞I/O模型 * 单线程非阻塞I/O模型 * 多线程非阻塞I/O模型,Reactor及其改进 前言 这里探讨的服务器模型主要指的是服务器端对I/O的处理模型。从不同维度可以有不同的分类,这里从I/O的阻塞与...
  • Java实现线程阻塞的两种方式

    千次阅读 2015-07-26 18:30:13
    最近参加公司的一个hackson比赛的时候,需要当前线程阻塞,并开启一个新的线程执行任务,任务执行完成后,再返回结果。线程相关的东西,用的都比较肤浅,所以当时只能在网上找了一堆文章,发现很多讲得比较繁琐,...
  • 线程阻塞原因

    千次阅读 2016-09-29 10:18:45
    线程在运行的过程中因为某些原因而发生阻塞阻塞状态的线程的特点是:该线程放弃CPU的使用,暂停运行,只有等到导致阻塞的原因消除之后才回复运行。或者是被其他的线程中断,该线程也会退出阻塞状态,同时抛出...
  • Java线程阻塞与中断

    千次阅读 2016-11-01 08:59:52
    线程阻塞和中断 1、线程阻塞 一个线程进入阻塞状态可能的原因: ①通过调用sleep(millseconds)使任务进入休眠状态; class Demo1 implements Runnable throws InterruptedException{  public void ...
  • Java线程阻塞的概念

    千次阅读 2014-01-20 22:48:33
    线程阻塞的原因 导致线程阻塞的原因主要由以下几方面。 1、线程执行了Thread.sleep(int n)方法,线程放弃CPU,睡眠n毫秒,然后恢复运行。 2、线程要执行一段同步代码,由于无法获得相关的同步锁,只好进入阻塞状态,...
  • 自己调试程序是可以执行,但是不调试运行,有写方法不走,是因为线程阻塞了吗,怎么解决线程阻塞
  • 查看线程阻塞线程栈

    千次阅读 2017-06-06 11:00:53
    我开发的worker,每隔几个月线上都会阻塞一次,一直都没查出问题。今天终于了了这个心结。把解决过程总结下和大家分享。  首先用jstack命令打出这个进程的全部线程堆栈。拿到线程dump文件之后,搜索自己的worker...
  • 进程与线程 阻塞与非阻塞

    千次阅读 2018-04-16 20:22:34
    线程:模块中的最小单元。cpu比作我们每个人,到饭点吃饭了。可以点很多菜(cpu中的进程):宫保鸡丁,鱼香肉丝,酸辣土豆丝。每样菜具体包含了哪些内容(cpu每个进程中的线程):宫保鸡丁(详情:黄瓜、胡萝卜、鸡肉、...
  • 线程阻塞方法

    千次阅读 2018-03-29 13:55:54
    //忍让一段时间wait方法:当调用wait方法后,当前线程会释放持有的monitor对象锁,因此,其他线程还可以进入到同步方法,线程被唤醒后(如果加时间参数的话,则会在时间被消耗后唤醒,否则需要通过notify或notifyall...
  • 线程阻塞控制工具类

    千次阅读 2019-06-21 08:53:17
    实现原理:让需要的暂时阻塞线程,进入一个死循环里面,得到某个条件后再退出循环,以此实现阻塞当前线程的效果。 public CountDownLatch(int count) { if (count < 0) throw new IllegalArgumentException(...
  • 线程并发学习—-线程阻塞(sleep、wait、notifyAll、notify) 线程并发学习—-线程阻塞(synchronized) 线程并发学习—-线程阻塞(concurrent包) 线程并发学习—-Thread、Runnable、Callable spring学习—-...
  • JavaFX线程阻塞问题

    千次阅读 2018-04-07 16:54:12
    在开发过程中遇到在JavaFX Controller中执行FTP上传文件操作时,JavaFX线程阻塞,对JavaFX界面的修改不执行的问题,尝试使用java.util.concurrent.FutureTask来执行上传功能,但依然失败。 调查之后,了解到原来...
  • 线程阻塞怎么结束

    千次阅读 2017-08-10 13:01:00
    线程有read, accept 之类阻塞的函数,如果主程序退出没有及时让子线程退出,子线程会奔溃。 解决方法:close 函数关闭对应的fd, 阻塞函数就会退出

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 615,602
精华内容 246,240
关键字:

线程的阻塞方式