精华内容
下载资源
问答
  • 写一个监听类,来监听我 “查询方法” ,用户再次执行查询方法后,我的监听类会根据“后台将查询出的数据拼成excel(此过程很耗时间)”是否完成,来返回给用户一个说明信息,让用户大致知道自己执行操作的...
  • 线程属于一次性消耗品,在执行完run()方法之后线程便会正常结束了,线程结束后便会销毁,不能再次start,只能重新建立新的线程对象,但有时run()方法是永远不会结束的。例如在程序中使用线程进行Socket监听请求,或是...

    线程属于一次性消耗品,在执行完run()方法之后线程便会正常结束了,线程结束后便会销毁,不能再次start,只能重新建立新的线程对象,但有时run()方法是永远不会结束的。例如在程序中使用线程进行Socket监听请求,或是其他的需要循环处理的任务。在这种情况下,一般是将这些任务放在一个循环中,如while循环。当需要结束线程时,如何退出线程呢?

    有三种方法可以结束线程:

    • 1.设置退出标志,使线程正常退出,也就是当run()方法完成后线程终止

    • 2.使用interrupt()方法中断线程

    • 3.使用stop方法强行终止线程(不推荐使用,Thread.stop, Thread.suspend, Thread.resume 和Runtime.runFinalizersOnExit 这些终止线程运行的方法已经被废弃,使用它们是极端不安全的!)

    前两种方法都可以实现线程的正常退出;第3种方法相当于电脑断电关机一样,是不安全的方法。

    1.使用退出标志终止线程
    一般run()方法执行完,线程就会正常结束,然而,常常有些线程是伺服线程。它们需要长时间的运行,只有在外部某些条件满足的情况下,才能关闭这些线程。使用一个变量来控制循环,例如:最直接的方法就是设一个boolean类型的标志,并通过设置这个标志为true或false来控制while循环是否退出,代码示例:

    public class ThreadSafe extends Thread {
        public volatile boolean exit = false; 
            public void run() { 
            while (!exit){
                //do something
            }
        } 
    }

    定义了一个退出标志exit,当exit为true时,while循环退出,exit的默认值为false.在定义exit时,使用了一个Java关键字volatile,这个关键字的目的是使exit同步,也就是说在同一时刻只能由一个线程来修改exit的值.

    2.使用interrupt()方法中断当前线程
    使用interrupt()方法来中断线程有两种情况:

    1.线程处于阻塞状态,如使用了sleep,同步锁的wait,socket中的receiver,accept等方法时,会使线程处于阻塞状态。当调用线程的interrupt()方法时,会抛出InterruptException异常。阻塞中的那个方法抛出这个异常,通过代码捕获该异常,然后break跳出循环状态,从而让我们有机会结束这个线程的执行。通常很多人认为只要调用interrupt方法线程就会结束,实际上是错的, 一定要先捕获InterruptedException异常之后通过break来跳出循环,才能正常结束run方法。

    代码示例:

    public class ThreadSafe extends Thread {
        public void run() { 
            while (true){
                try{
                        Thread.sleep(5*1000);//阻塞5妙
                    }catch(InterruptedException e){
                        e.printStackTrace();
                        break;//捕获到异常之后,执行break跳出循环。
                    }
            }
        } 
    }

    2.线程未处于阻塞状态,使用isInterrupted()判断线程的中断标志来退出循环。当使用interrupt()方法时,中断标志就会置true,和使用自定义的标志来控制循环是一样的道理。

    代码示例:

    public class ThreadSafe extends Thread {
        public void run() { 
            while (!isInterrupted()){
                //do something, but no throw InterruptedException
            }
        } 
    }

    为什么要区分进入阻塞状态和和非阻塞状态两种情况了,是因为当阻塞状态时,如果有interrupt()发生,系统除了会抛出InterruptedException异常外,还会调用interrupted()函数,调用时能获取到中断状态是true的状态,调用完之后会复位中断状态为false,所以异常抛出之后通过isInterrupted()是获取不到中断状态是true的状态,从而不能退出循环,因此在线程未进入阻塞的代码段时是可以通过isInterrupted()来判断中断是否发生来控制循环,在进入阻塞状态后要通过捕获异常来退出循环。因此使用interrupt()来退出线程的最好的方式应该是两种情况都要考虑:

    代码示例:

    public class ThreadSafe extends Thread {
        public void run() { 
            while (!isInterrupted()){ //非阻塞过程中通过判断中断标志来退出
                try{
                    Thread.sleep(5*1000);//阻塞过程捕获中断异常来退出
                }catch(InterruptedException e){
                    e.printStackTrace();
                    break;//捕获到异常之后,执行break跳出循环。
                }
            }
        } 
    }

    3.使用stop方法终止线程
    程序中可以直接使用thread.stop()来强行终止线程,但是stop方法是很危险的,就象突然关闭计算机电源,而不是按正常程序关机一样,可能会产生不可预料的结果,不安全主要是:thread.stop()调用之后,创建子线程的线程就会抛出ThreadDeatherror的错误,并且会释放子线程所持有的所有锁。一般任何进行加锁的代码块,都是为了保护数据的一致性,如果在调用thread.stop()后导致了该线程所持有的所有锁的突然释放(不可控制),那么被保护数据就有可能呈现不一致性,其他线程在使用这些被破坏的数据时,有可能导致一些很奇怪的应用程序错误。因此,并不推荐使用stop方法来终止线程。

    展开全文
  • UI展示完毕之后初始线程就结束了,控制就交给了事件派发线程,这之后所有组件的事件行为都由事件派发线程处理,事件派发线程是调用paint和update等回调方法的线程,它还是事件监听器接口中定义的事件处理方法,也...

    在用swing做项目时,点击swing页面1的按钮打开页面2,会出现卡死现象。但是直接通过页面2的main方法打开页面2,却能打开。具体描述就是按下一个按钮执行任务,接着按钮就一直是按下的状态,界面卡死。

    原因是swing是线程不安全的,是单线程设计。Swing有初始线程,事件派发线程,工作线程。UI展示完毕之后初始线程就结束了,控制就交给了事件派发线程,这之后所有组件的事件行为都由事件派发线程处理,事件派发线程是调用paint和update等回调方法的线程,它还是事件监听器接口中定义的事件处理方法,也就是说只能从事件派发线程访问组件。这就是真相了,程序由事件派发线程执行一个任务,这时就要等待这个线程处理完这个任务,所以界面出现卡死现象,等这个任务结束了,事件派发线程就可以更新组件,就恢复正常了。所以,一些长时间的任务就要交给工作线程处理。

    解决办法就是把耗时长的任务单独开一个线程处理,即工作线程。

    我把页面2的类实现了runnable接口,通过thread打开页面2,成功解决了卡死问题。

    参考资料https://www.lsablog.com/program/java/java-swing-ui-stuck-solution/

    展开全文
  • 线程属于一次性消耗品,在执行完run()方法之后线程便会正常结束了,线程结束后便会销毁,不能再次start,只能重新建立新的线程对象,但有时run()方法是永远不会结束的。例如在程序中使用线程进行Socket监听请求,或是...

    背景:面试过程中问到结束线程的方法和线程池shutdown shutdownnow区别以及底层的实现,当时答的并不好。

    Java结束线程的三种方法

    线程属于一次性消耗品,在执行完run()方法之后线程便会正常结束了,线程结束后便会销毁,不能再次start,只能重新建立新的线程对象,但有时run()方法是永远不会结束的。例如在程序中使用线程进行Socket监听请求,或是其他的需要循环处理的任务。在这种情况下,一般是将这些任务放在一个循环中,如while循环。当需要结束线程时,如何退出线程呢?

    有三种方法可以结束线程:

    • 1.设置退出标志,使线程正常退出,也就是当run()方法完成后线程终止

    • 2.使用interrupt()方法中断线程

    • 3.使用stop方法强行终止线程(不推荐使用,Thread.stop, Thread.suspend, Thread.resume 和Runtime.runFinalizersOnExit 这些终止线程运行的方法已经被废弃,使用它们是极端不安全的!)

    前两种方法都可以实现线程的正常退出;第3种方法相当于电脑断电关机一样,是不安全的方法

    1.使用退出标志终止线程 
    一般run()方法执行完,线程就会正常结束,然而,常常有些线程是伺服线程。它们需要长时间的运行,只有在外部某些条件满足的情况下,才能关闭这些线程。使用一个变量来控制循环,例如:最直接的方法就是设一个boolean类型的标志,并通过设置这个标志为true或false来控制while循环是否退出,代码示例:

    public class ThreadSafe extends Thread {
        public volatile boolean exit = false; 
            public void run() { 
            while (!exit){
                //do something
            }
        } 
    }

     

    定义了一个退出标志exit,当exit为true时,while循环退出,exit的默认值为false.在定义exit时,使用了一个Java关键字volatile,这个关键字的目的是使exit同步,也就是说在同一时刻只能由一个线程来修改exit的值.

    2.使用interrupt()方法中断当前线程 
    使用interrupt()方法来中断线程有两种情况:

    1.线程处于阻塞状态,如使用了sleep,同步锁的wait,socket中的receiver,accept等方法时,会使线程处于阻塞状态。当调用线程的interrupt()方法时,会抛出InterruptException异常。阻塞中的那个方法抛出这个异常,通过代码捕获该异常,然后break跳出循环状态,从而让我们有机会结束这个线程的执行。通常很多人认为只要调用interrupt方法线程就会结束,实际上是错的, 一定要先捕获InterruptedException异常之后通过break来跳出循环,才能正常结束run方法。

    代码示例:

    public class ThreadSafe extends Thread {
        public void run() { 
            while (true){
                try{
                        Thread.sleep(5*1000);//阻塞5妙
                    }catch(InterruptedException e){
                        e.printStackTrace();
                        break;//捕获到异常之后,执行break跳出循环。
                    }
            }
        } 
    }

    2.线程未处于阻塞状态,使用isInterrupted()判断线程的中断标志来退出循环。当使用interrupt()方法时,中断标志就会置true,和使用自定义的标志来控制循环是一样的道理。 
    代码示例:

    public class ThreadSafe extends Thread {
        public void run() { 
            while (!isInterrupted()){
                //do something, but no throw InterruptedException
            }
        } 
    }

    为什么要区分进入阻塞状态和和非阻塞状态两种情况了,是因为当阻塞状态时,如果有interrupt()发生,系统除了会抛出InterruptedException异常外,还会调用interrupted()函数,调用时能获取到中断状态是true的状态,调用完之后会复位中断状态为false,所以异常抛出之后通过isInterrupted()是获取不到中断状态是true的状态,从而不能退出循环,因此在线程未进入阻塞的代码段时是可以通过isInterrupted()来判断中断是否发生来控制循环,在进入阻塞状态后要通过捕获异常来退出循环。因此使用interrupt()来退出线程的最好的方式应该是两种情况都要考虑:

    代码示例:

    public class ThreadSafe extends Thread {
        public void run() { 
            while (!isInterrupted()){ //非阻塞过程中通过判断中断标志来退出
                try{
                    Thread.sleep(5*1000);//阻塞过程捕获中断异常来退出
                }catch(InterruptedException e){
                    e.printStackTrace();
                    break;//捕获到异常之后,执行break跳出循环。
                }
            }
        } 
    }

    3.使用stop方法终止线程 
    程序中可以直接使用thread.stop()来强行终止线程,但是stop方法是很危险的,就象突然关闭计算机电源,而不是按正常程序关机一样,可能会产生不可预料的结果,不安全主要是:thread.stop()调用之后,创建子线程的线程就会抛出ThreadDeatherror的错误,并且会释放子线程所持有的所有锁。一般任何进行加锁的代码块,都是为了保护数据的一致性,如果在调用thread.stop()后导致了该线程所持有的所有锁的突然释放(不可控制),那么被保护数据就有可能呈现不一致性,其他线程在使用这些被破坏的数据时,有可能导致一些很奇怪的应用程序错误。因此,并不推荐使用stop方法来终止线程。

     

    interrupt、interrupted 、isInterrupted 区别

     

    interrupt、interrupted 、isInterrupted 区别

    1、interrupt 

    interrupt方法用于中断线程。调用该方法的线程的状态为将被置为"中断"状态。
    注意:线程中断仅仅是置线程的中断状态位,不会停止线程。需要用户自己去监视线程的状态为并做处理。支持线程中断的方法(也就是线程中断后会抛出interruptedException的方法)就是在监视线程的中断状态,一旦线程的中断状态被置为“中断状态”,就会抛出中断异常。
        public void interrupt() {
            if (this != Thread.currentThread())
                checkAccess();
    
            synchronized (blockerLock) {
                Interruptible b = blocker;
                if (b != null) {
                    interrupt0();           // Just to set the interrupt flag
                    b.interrupt(this);
                    return;
                }
            }
            interrupt0();
        }
    
        private native void interrupt0();

     

    interrupt 设置中断状态。

    2、interrupted 和 isInterrupted

    首先看一下该方法的实现:
        public static boolean interrupted() {
            return currentThread().isInterrupted(true);
        }
    该方法就是直接调用当前线程的isInterrupted(true)方法。
    静态方法,返回当前的线程的状态,并会清楚之前的状态。
    然后再来看一下 isInterrupted的实现:
        public boolean isInterrupted() {
            return isInterrupted(false);
        }

    只会返回当前线程的状态,并不会清除。 

    底层都是调用一个本地方法:

        /**
         * Tests if some Thread has been interrupted.  The interrupted state
         * is reset or not based on the value of ClearInterrupted that is
         * passed.
         */
        private native boolean isInterrupted(boolean ClearInterrupted);

     

    原来这是一个本地方法,看不到源码。不过没关系,通过参数名我们就能知道,这个参数代表是否要清除状态位。

    如果这个参数为true,说明返回线程的状态位后,要清掉原来的状态位(恢复成原来情况)。这个参数为false,就是直接返回线程的状态位。

    这两个方法很好区分,只有当前线程才能清除自己的中断位(对应interrupted()方法)

     

    interrupted 和 isInterrupted

    这两个方法有两个主要区别:
    1. interrupted 是作用于当前线程,isInterrupted 是作用于调用该方法的线程对象所对应的线程。(线程对象对应的线程不一定是当前运行的线程。例如我们可以在A线程中去调用B线程对象的isInterrupted方法。)
    2. 这两个方法最终都会调用同一个方法,只不过参数一个是true,一个是false;

    是不是这样理解呢,
    Thread.currentThread().interrupted(); 这个用于清除中断状态,这样下次调用Thread.interrupted()方法时就会一直返回为false,因为中断标志已经被恢复了。
    而调用isInterrupted 只是简单的查询中断状态,不会对状态进行修改。

    interrupt()是用来设置中断状态的。返回true说明中断状态被设置了而不是被清除了。我们调用sleep、wait等此类可中断(throw InterruptedException)方法时,一旦方法抛出InterruptedException,当前调用该方法的线程的中断状态就会被jvm自动清除了,就是说我们调用该线程的isInterrupted 方法时是返回false。如果你想保持中断状态,可以再次调用interrupt方法设置中断状态。这样做的原因是,java的中断并不是真正的中断线程,而只设置标志位(中断位)来通知用户。如果你捕获到中断异常,说明当前线程已经被中断,不需要继续保持中断位。
    interrupted是静态方法,返回的是当前线程的中断状态。例如,如果当前线程被中断(没有抛出中断异常,否则中断状态就会被清除),你调用interrupted方法,第一次会返回true。然后,当前线程的中断状态被方法内部清除了。第二次调用时就会返回false。如果你刚开始一直调用isInterrupted,则会一直返回true,除非中间线程的中断状态被其他操作清除了。

     

    https://github.com/CyC2018/CS-Notes/blob/master/docs/notes/Java%20%E5%B9%B6%E5%8F%91.md#interrupted

    ps:里面有interrupted()相关的详细使用例子。

     

    调用 Executor 的 shutdown() 方法会等待线程都执行完毕之后再关闭,但是如果调用的是 shutdownNow() 方法,则相当于调用每个线程的 interrupt() 方法。

    如果只想中断 Executor 中的一个线程,可以通过使用 submit() 方法来提交一个线程,它会返回一个 Future<?> 对象,通过调用该对象的 cancel(true) 方法就可以中断线程。

    Future<?> future = executorService.submit(() -> {
        // ..
    });
    future.cancel(true);

    threadPoolExecutor 中的 shutdown() 、 shutdownNow() 、 awaitTermination() 的用法和区别

    threadPoolExecutor 中的 shutdown() 、 shutdownNow() 、 awaitTermination() 的用法和区别

    最近在看并发编程,在使用到ThreadPoolExecutor时,对它的三个关闭方法(shutdown()、shutdownNow()、awaitTermination())产生了兴趣,同时又感到迷惑。查了些资料,自己写了测试代码,总算有了个比较清晰的认识。下面一起来看看这三个方法:

    shutdown()

    将线程池状态置为SHUTDOWN,并不会立即停止:

    • 停止接收外部submit的任务
    • 内部正在跑的任务和队列里等待的任务,会执行完
    • 等到第二步完成后,才真正停止

    shutdownNow()

    线程池状态置为STOP。企图立即停止,事实上不一定:

    跟shutdown()一样,

    • 先停止接收外部提交的任务
    • 忽略队列里等待的任务
    • 尝试将正在跑的任务interrupt中断
    • 返回未执行的任务列表

    它试图终止线程的方法是通过调用Thread.interrupt()方法来实现的,但是大家知道,这种方法的作用有限,如果线程中没有sleep 、wait、Condition、定时锁等应用, interrupt()方法是无法中断当前的线程的。所以,ShutdownNow()并不代表线程池就一定立即就能退出,它也可能必须要等待所有正在执行的任务都执行完成了才能退出。

    但是大多数时候是能立即退出的

    awaitTermination(long timeOut, TimeUnit unit)

    当前线程阻塞,直到

    • 等所有已提交的任务(包括正在跑的和队列中等待的)执行完
    • 或者等超时时间到
    • 或者线程被中断,抛出InterruptedException
    • 然后返回true(shutdown请求后所有任务执行完毕)或false(已超时)

    实验发现,shuntdown()和awaitTermination()效果差不多,方法执行之后,都要等到提交的任务全部执行完才停。

    shutdown()和shutdownNow()的区别

    从字面意思就能理解,shutdownNow()能立即停止线程池,正在跑的和正在等待的任务都停下了。这样做立即生效,但是风险也比较大;
    shutdown()只是关闭了提交通道,用submit()是无效的;而内部该怎么跑还是怎么跑,跑完再停。

    Between client threads and thread pool there is a queue of tasks. When your application shuts down, you must take care of two things: what is happening with queued tasks and how already running tasks are behaving (more on that later). Surprisingly many developers are not shutting down thread pool properly or consciously. There are two techniques: either let all queued tasks to execute (shutdown()) or drop them (shutdownNow()) - it totally depends on your use case.

    shutdown()和awaitTermination()的区别
    shutdown()后,不能再提交新的任务进去;但是awaitTermination()后,可以继续提交。
    awaitTermination()是阻塞的,返回结果是线程池是否已停止(true/false);shutdown()不阻塞。

    总结

    优雅的关闭,用shutdown()
    想立马关闭,并得到未执行任务列表,用shutdownNow()
    优雅的关闭,并允许关闭声明后新任务能提交,用awaitTermination()
    关闭功能 【从强到弱】 依次是:shuntdownNow() > shutdown() > awaitTermination()

    线程池的状态

    Java多线程线程池(4)--线程池的五种状态

    线程池的5种状态:Running、ShutDown、Stop、Tidying、Terminated

    线程池各个状态切换框架图:

    image

     

    转载于:https://www.cnblogs.com/lixuwu/p/10766125.html

    展开全文
  • 线程属于一次性消耗品,在执行完run()方法之后线程便会正常结束了,线程结束后便会销毁,不能再次start,只能重新建立新的线程对象,但有时run()方法是永远不会结束的。例如在程序中使用线程进行Socket监听请求,或是...

    背景:面试过程中问到结束线程的方法和线程池shutdown shutdownnow区别以及底层的实现,当时答的并不好。

    线程属于一次性消耗品,在执行完run()方法之后线程便会正常结束了,线程结束后便会销毁,不能再次start,只能重新建立新的线程对象,但有时run()方法是永远不会结束的。例如在程序中使用线程进行Socket监听请求,或是其他的需要循环处理的任务。在这种情况下,一般是将这些任务放在一个循环中,如while循环。当需要结束线程时,如何退出线程呢?

    有三种方法可以结束线程:

    1.设置退出标志,使线程正常退出,也就是当run()方法完成后线程终止

    2.使用interrupt()方法中断线程

    3.使用stop方法强行终止线程(不推荐使用,Thread.stop, Thread.suspend, Thread.resume 和Runtime.runFinalizersOnExit 这些终止线程运行的方法已经被废弃,使用它们是极端不安全的!)

    前两种方法都可以实现线程的正常退出;第3种方法相当于电脑断电关机一样,是不安全的方法。

    1.使用退出标志终止线程

    一般run()方法执行完,线程就会正常结束,然而,常常有些线程是伺服线程。它们需要长时间的运行,只有在外部某些条件满足的情况下,才能关闭这些线程。使用一个变量来控制循环,例如:最直接的方法就是设一个boolean类型的标志,并通过设置这个标志为true或false来控制while循环是否退出,代码示例:

    public class ThreadSafe extendsThread {public volatile boolean exit = false;public voidrun() {while (!exit){//do something

    }

    }

    }

    定义了一个退出标志exit,当exit为true时,while循环退出,exit的默认值为false.在定义exit时,使用了一个Java关键字volatile,这个关键字的目的是使exit同步,也就是说在同一时刻只能由一个线程来修改exit的值.

    2.使用interrupt()方法中断当前线程

    使用interrupt()方法来中断线程有两种情况:

    1.线程处于阻塞状态,如使用了sleep,同步锁的wait,socket中的receiver,accept等方法时,会使线程处于阻塞状态。当调用线程的interrupt()方法时,会抛出InterruptException异常。阻塞中的那个方法抛出这个异常,通过代码捕获该异常,然后break跳出循环状态,从而让我们有机会结束这个线程的执行。通常很多人认为只要调用interrupt方法线程就会结束,实际上是错的, 一定要先捕获InterruptedException异常之后通过break来跳出循环,才能正常结束run方法。

    代码示例:

    public class ThreadSafe extendsThread {public voidrun() {while (true){try{

    Thread.sleep(5*1000);//阻塞5妙

    }catch(InterruptedException e){

    e.printStackTrace();break;//捕获到异常之后,执行break跳出循环。

    }

    }

    }

    }

    2.线程未处于阻塞状态,使用isInterrupted()判断线程的中断标志来退出循环。当使用interrupt()方法时,中断标志就会置true,和使用自定义的标志来控制循环是一样的道理。

    代码示例:

    public class ThreadSafe extendsThread {public voidrun() {while (!isInterrupted()){//do something, but no throw InterruptedException

    }

    }

    }

    为什么要区分进入阻塞状态和和非阻塞状态两种情况了,是因为当阻塞状态时,如果有interrupt()发生,系统除了会抛出InterruptedException异常外,还会调用interrupted()函数,调用时能获取到中断状态是true的状态,调用完之后会复位中断状态为false,所以异常抛出之后通过isInterrupted()是获取不到中断状态是true的状态,从而不能退出循环,因此在线程未进入阻塞的代码段时是可以通过isInterrupted()来判断中断是否发生来控制循环,在进入阻塞状态后要通过捕获异常来退出循环。因此使用interrupt()来退出线程的最好的方式应该是两种情况都要考虑:

    代码示例:

    public class ThreadSafe extendsThread {public voidrun() {while (!isInterrupted()){ //非阻塞过程中通过判断中断标志来退出

    try{

    Thread.sleep(5*1000);//阻塞过程捕获中断异常来退出

    }catch(InterruptedException e){

    e.printStackTrace();break;//捕获到异常之后,执行break跳出循环。

    }

    }

    }

    }

    3.使用stop方法终止线程

    程序中可以直接使用thread.stop()来强行终止线程,但是stop方法是很危险的,就象突然关闭计算机电源,而不是按正常程序关机一样,可能会产生不可预料的结果,不安全主要是:thread.stop()调用之后,创建子线程的线程就会抛出ThreadDeatherror的错误,并且会释放子线程所持有的所有锁。一般任何进行加锁的代码块,都是为了保护数据的一致性,如果在调用thread.stop()后导致了该线程所持有的所有锁的突然释放(不可控制),那么被保护数据就有可能呈现不一致性,其他线程在使用这些被破坏的数据时,有可能导致一些很奇怪的应用程序错误。因此,并不推荐使用stop方法来终止线程。

    interrupt、interrupted 、isInterrupted 区别

    1、interrupt

    interrupt方法用于中断线程。调用该方法的线程的状态为将被置为"中断"状态。

    注意:线程中断仅仅是置线程的中断状态位,不会停止线程。需要用户自己去监视线程的状态为并做处理。支持线程中断的方法(也就是线程中断后会抛出interruptedException的方法)就是在监视线程的中断状态,一旦线程的中断状态被置为“中断状态”,就会抛出中断异常。

    public voidinterrupt() {if (this !=Thread.currentThread())

    checkAccess();synchronized(blockerLock) {

    Interruptible b=blocker;if (b != null) {

    interrupt0();//Just to set the interrupt flag

    b.interrupt(this);return;

    }

    }

    interrupt0();

    }private native void interrupt0();

    interrupt 设置中断状态。

    2、interrupted 和 isInterrupted

    首先看一下该方法的实现:

    public static booleaninterrupted() {return currentThread().isInterrupted(true);

    }

    该方法就是直接调用当前线程的isInterrupted(true)方法。

    静态方法,返回当前的线程的状态,并会清楚之前的状态。

    然后再来看一下 isInterrupted的实现:

    public booleanisInterrupted() {return isInterrupted(false);

    }

    只会返回当前线程的状态,并不会清除。

    底层都是调用一个本地方法:

    /*** Tests if some Thread has been interrupted. The interrupted state

    * is reset or not based on the value of ClearInterrupted that is

    * passed.*/

    private native boolean isInterrupted(boolean ClearInterrupted);

    原来这是一个本地方法,看不到源码。不过没关系,通过参数名我们就能知道,这个参数代表是否要清除状态位。

    如果这个参数为true,说明返回线程的状态位后,要清掉原来的状态位(恢复成原来情况)。这个参数为false,就是直接返回线程的状态位。

    这两个方法很好区分,只有当前线程才能清除自己的中断位(对应interrupted()方法)

    interrupted 和 isInterrupted

    这两个方法有两个主要区别:

    interrupted 是作用于当前线程,isInterrupted 是作用于调用该方法的线程对象所对应的线程。(线程对象对应的线程不一定是当前运行的线程。例如我们可以在A线程中去调用B线程对象的isInterrupted方法。)

    这两个方法最终都会调用同一个方法,只不过参数一个是true,一个是false;

    是不是这样理解呢,

    Thread.currentThread().interrupted(); 这个用于清除中断状态,这样下次调用Thread.interrupted()方法时就会一直返回为false,因为中断标志已经被恢复了。

    而调用isInterrupted 只是简单的查询中断状态,不会对状态进行修改。

    interrupt()是用来设置中断状态的。返回true说明中断状态被设置了而不是被清除了。我们调用sleep、wait等此类可中断(throw InterruptedException)方法时,一旦方法抛出InterruptedException,当前调用该方法的线程的中断状态就会被jvm自动清除了,就是说我们调用该线程的isInterrupted 方法时是返回false。如果你想保持中断状态,可以再次调用interrupt方法设置中断状态。这样做的原因是,java的中断并不是真正的中断线程,而只设置标志位(中断位)来通知用户。如果你捕获到中断异常,说明当前线程已经被中断,不需要继续保持中断位。

    interrupted是静态方法,返回的是当前线程的中断状态。例如,如果当前线程被中断(没有抛出中断异常,否则中断状态就会被清除),你调用interrupted方法,第一次会返回true。然后,当前线程的中断状态被方法内部清除了。第二次调用时就会返回false。如果你刚开始一直调用isInterrupted,则会一直返回true,除非中间线程的中断状态被其他操作清除了。

    ps:里面有interrupted()相关的详细使用例子。

    调用 Executor 的 shutdown() 方法会等待线程都执行完毕之后再关闭,但是如果调用的是 shutdownNow() 方法,则相当于调用每个线程的 interrupt() 方法。

    如果只想中断 Executor 中的一个线程,可以通过使用 submit() 方法来提交一个线程,它会返回一个 Future> 对象,通过调用该对象的 cancel(true) 方法就可以中断线程。

    Future> future = executorService.submit(() ->{//..

    });

    future.cancel(true);

    threadPoolExecutor 中的 shutdown() 、 shutdownNow() 、 awaitTermination() 的用法和区别

    最近在看并发编程,在使用到ThreadPoolExecutor时,对它的三个关闭方法(shutdown()、shutdownNow()、awaitTermination())产生了兴趣,同时又感到迷惑。查了些资料,自己写了测试代码,总算有了个比较清晰的认识。下面一起来看看这三个方法:

    shutdown()

    将线程池状态置为SHUTDOWN,并不会立即停止:

    停止接收外部submit的任务

    内部正在跑的任务和队列里等待的任务,会执行完

    等到第二步完成后,才真正停止

    shutdownNow()

    将线程池状态置为STOP。企图立即停止,事实上不一定:

    跟shutdown()一样,

    先停止接收外部提交的任务

    忽略队列里等待的任务

    尝试将正在跑的任务interrupt中断

    返回未执行的任务列表

    它试图终止线程的方法是通过调用Thread.interrupt()方法来实现的,但是大家知道,这种方法的作用有限,如果线程中没有sleep 、wait、Condition、定时锁等应用, interrupt()方法是无法中断当前的线程的。所以,ShutdownNow()并不代表线程池就一定立即就能退出,它也可能必须要等待所有正在执行的任务都执行完成了才能退出。

    但是大多数时候是能立即退出的

    awaitTermination(long timeOut, TimeUnit unit)

    当前线程阻塞,直到

    等所有已提交的任务(包括正在跑的和队列中等待的)执行完

    或者等超时时间到

    或者线程被中断,抛出InterruptedException

    然后返回true(shutdown请求后所有任务执行完毕)或false(已超时)

    实验发现,shuntdown()和awaitTermination()效果差不多,方法执行之后,都要等到提交的任务全部执行完才停。

    shutdown()和shutdownNow()的区别

    从字面意思就能理解,shutdownNow()能立即停止线程池,正在跑的和正在等待的任务都停下了。这样做立即生效,但是风险也比较大;

    shutdown()只是关闭了提交通道,用submit()是无效的;而内部该怎么跑还是怎么跑,跑完再停。

    Between client threads and thread pool there is a queue of tasks. When your application shuts down, you must take care of two things: what is happening with queued tasks and how already running tasks are behaving (more on that later). Surprisingly many developers are not shutting down thread pool properly or consciously. There are two techniques: either let all queued tasks to execute (shutdown()) or drop them (shutdownNow()) - it totally depends on your use case.

    shutdown()和awaitTermination()的区别

    shutdown()后,不能再提交新的任务进去;但是awaitTermination()后,可以继续提交。

    awaitTermination()是阻塞的,返回结果是线程池是否已停止(true/false);shutdown()不阻塞。

    总结

    优雅的关闭,用shutdown()

    想立马关闭,并得到未执行任务列表,用shutdownNow()

    优雅的关闭,并允许关闭声明后新任务能提交,用awaitTermination()

    关闭功能 【从强到弱】 依次是:shuntdownNow() > shutdown() > awaitTermination()

    线程池的状态

    线程池的5种状态:Running、ShutDown、Stop、Tidying、Terminated。

    线程池各个状态切换框架图:

    98e3e725347abe453b5c535f1bd59b2f.png

    展开全文
  • 线程属于一次性消耗品,在执行完run()方法之后线程便会正常结束了,线程结束后便会销毁,不能再次start,只能重新建立新的线程对象,但有时run()方法是永远不会结束的。例如在程序中使用线程进行Socket监听请求,或是...
  • 这是一个按钮监听(b是按钮,f是JFrame的对象),如果我在里面用Thread.sleep()方法休眠,会出现窗体,但是内容不会显示(休眠结束后窗体就执行最后的语句消失了),后来我把最后的f.setVisible(false);换成了System...
  • java 线程退出方法

    千次阅读 2019-06-18 10:30:47
    Android终止线程的方法 线程对象属于一次性消耗品,一般线程执行完run方法之后,线程就正常结束了,线程...1. 使用退出标志,使线程正常退出,也就是当run方法完成线程终止 2. 使用interrupt()方法中断线程 3....
  • 线程属于一次性消耗品,在执行完run()方法之后线程便会正常结束了,线程结束后便会销毁,不能再次start,只能重新建立新的线程对象,但有时run()方法是永远不会结束的。例如在程序中使用线程进行Socket监听请求,或是...
  • Java。在Java中停止线程的三种方法

    千次阅读 2018-03-06 14:34:29
    1. 使用退出标志,使线程正常退出,也就是当run方法完成线程终止。 2. 使用stop方法强行终止线程(这个方法不推荐使用,因为...但有时run方法是永远不会结束的。如在服务端程序中使用线程进行监听客户端请求,...
  • 这会导致Tomcat 服务器停止后Java进程尚未停止, 继续占用内存, 必须通过 类似 kill -9 之类的命令去杀死java进程. 这是由于在服务器停止时有些线程尚未销毁所引起的, 如ThreadLocal; Scheduler 启动的线程; JDBC ...
  • Java Rest请求工具一、添加依赖...在请求结束后,可以通过get()方法获取返回的内容,也可以通过listener()方法指定监听者去监听结果返回后的处理逻辑1、无参数请求public class Test{public sta...
  • Java Rest请求工具一、添加依赖...在请求结束后,可以通过get()方法获取返回的内容,也可以通过listener()方法指定监听者去监听结果返回后的处理逻辑1、无参数请求public class Test{public sta...
  • Java学习日记:五子棋

    2020-06-21 22:43:41
    文章目录Java学习日记:五子棋介绍下棋判断输赢循环进行实现方法具体步骤棋盘界面棋盘动作监听结束界面结束界面监听Java学习日记:五子棋 介绍 使用Java实现一个简单的带界面的五子棋游戏。 流程: Created ...
  • 2.利用testng的监听类在测试方法运行结束后进行分析。代码:断言类:package com.demo;import java.util.ArrayList;import java.util.List;import org.testng.Assert;public class Assertion {pu...
  • java调用zookeeper API demo

    千次阅读 2016-11-16 00:53:24
    使用Thread.sleep()这个方法是防止查看完成后java程序就执行结束了,导致监听不到变化,其中这里的getChildren()监听相当于zookeeper在shell下的ls path watch一样的效果。2.zookeeper的监听只会被执行一次,如果...
  • <div><pre><code>java public void setChecked(boolean checked) { if(checked == isChecked()){ postInvalidate(); return; } toggle(enableEffect, false); } </code></pre> 当状态不相同时࿰...
  • 疯狂JAVA讲义

    2014-10-17 13:35:01
    4.4.3 使用return结束方法 87 4.5 数组类型 87 4.5.1 理解数组:数组也是一种类型 88 学生提问:int[]是一种类型吗?怎么使用这种类型呢? 88 4.5.2 定义数组 88 4.5.3 数组的初始化 89 学生提问:能不能只...
  • Java开发技术大全(500个源代码).

    热门讨论 2012-12-02 19:55:48
    demoJoin.java 演示使用join()以确保主线程最后结束 clicker.java 一个计数用的线程类 demoPri.java 调用上面这个类设置线程优先级示例 myThread.java 自己定义的一个Thread的子类 mutexThread.java 一个能管理...
  • 有时候我们会遇到这样的场景 客户端请求一个接口,返回需要的数据,然后根据这些数据做相应的操作,然后这个接口还要等待...在java中,单线程情况下执行return整个方法结束了,所以要完成上面的需求,就需要我们
  • java web中的Session 在JavaWeb中使用HttpSession(以下简称session)对象来表示一个会话。...Session的销毁(代表会话周期的结束):在某个请求周期内调用了Session.invalidate()方法,此请求周期结束后...
  • java基础---线程的停止

    2017-12-07 20:28:19
    但有时run方法是永远不会结束的。如在 服务端程序中使用线程进行监听客户端请求,或是其他的需要循环处理的任务。 在这种情况下,一般是将这些任务放在一个循环中,如while循环。如果想让循 环永远运行下去,可以...
  • Java典型模块

    2012-02-25 18:27:40
    5.3.3 线程的结束状态 5.4 小结 第6章 火车站售票系统(线程安全知识) 6.1 火车站售票系统原理 6.1.1 项目结构框架分析 6.1.2 项目功能业务分析 6.2 没有实现线程安全的火车票售票系统 6.2.1 火车票的类 6.2.2 售票...

空空如也

空空如也

1 2 3 4
收藏数 75
精华内容 30
关键字:

java监听方法结束后

java 订阅