zoukankan      html  css  js  c++  java
  • 如何中断“同步/阻塞”线程,not only interrupt()

    如何中断一个正在执行的线程?

    线程中断,意味着该线程在完成任务之前停止其正在进行的一切,有效地中止其当前的操作。

    那么,线程接下为是死亡、还是等待新的任务,或是继续运行至下一步。

    【方法一】使用共享变量Shared Variable

    1. 需要线程“周期性”的核查这一变量,然后有秩序的中止任务。

    2. 将共享变量定义成“volatile”型,或将它的一切方法封入“synchronized”块或方法中。

    3. 局限性:如果线程被阻塞,便不能核查共享变量,该方法将失效。例如,Object.wait(), ServerSocket.accept()和DatagramSocket.receive(),等等。

    public class Main extends Thread {
     
        volatile boolean stop = false;
     
        public static void main(String[] args) {
     
            Main thread = new Main();
     
            try {
                System.out.println("starting thread");
                thread.start();
                Thread.sleep(3000);
                System.out.println("asking thread to stop");
                thread.stop = true;
                Thread.sleep(3000);
                System.out.println("stopping application");
            } catch (InterruptedException e) {
                System.out.println("sleep interrupted");
                ;
            }
        }
     
        public void run() {
            while (!stop) { // 周期性的检查
                System.out.println("running");
                long time = System.currentTimeMillis();
                while (System.currentTimeMillis() - time < 1000) {
                    ;
                }
            }
            System.out.println("thread exiting under request..");
        }
    }

    【方法二】对于阻塞情况,使用Thread.interrupt()

    (1)interrupt(),不会中断一个正在运行的线程,它实际完成的是,在线程“受到阻塞时”抛出一个中断信号,这样线程就得以退出阻塞状态。更确定的说,如果线程被Object.wait(), Thread.join()和Thread.sleep()三种方法之一阻塞,那么,它将接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态。

    (2)局限性:interrupt(),可以很好的解救阻塞中的线程,但如果一直占用着CPU就仍然中断不了.

    public class Main extends Thread {
        boolean stop = false;
        public static void main(String[] args) {
            Main thread = new Main();
            try {
                System.out.println("starting thread");
                thread.start();
                Thread.sleep(3000);
                System.out.println("asking thread to stop");
                thread.stop = true; // 如果线程阻塞,将不会检查此变量
                thread.interrupt(); // 中断
                Thread.sleep(3000);
                System.out.println("stopping application");
            } catch (InterruptedException e) {
                System.out.println("sleep interrupted");
                ;
            }
        }
     
        public void run() {
            while (!stop) {
                System.out.println("running");
                try{
                    Thread.sleep(1000);
                }catch(InterruptedException e){
                    System.out.println("Thread interrupted");
                }
            }
            System.out.println("thread exiting under request..");
        }
    }

    【方法三】“野蛮”行径,未尝不可

    (1)对于同步情况,可以开“捣乱”线程,强抛RuntimeException

    例如,同步等待在主线程A中做,那么:

    a) 在A中中开线程B,做的事情:sleep(timeout)时间,醒了就抛出RuntimeException;

    b) 在A中做一些事情,同步神马的亦可;

    c) timeout时间到,若2)仍未结束,RuntimeException也会使其结束的;

    (2)劣势:这种方法,强抛runtimeException出来,无法catch,自然也就意味着不能做任何处理,眼睁睁的看着它抛。

    Semaphore s = new Semaphore(0);
    TimeoutThread t = new TimeoutThread(5000L, new TimeoutException("超时"));
    try {
        t.start();
        
        // 同步等待代码
        System.out.println("try to acquire");
        s.acquire();
        System.out.println("acquired");
        
        t.cancel();
    }catch (InterruptedException e) {
        System.out.println("interrupt exception");
    }

    【方法四】……

    【备注】:

    (1)不推荐使用:Thread.stop()

    (2)这样使用interrupt,并不能真正中断线程,所以不要被名字蒙蔽了:

    public class Main extends Thread {
     
        volatile boolean stop = false;
     
        public static void main(String[] args) {
     
            Main thread = new Main();
     
            try {
                System.out.println("starting thread");
                thread.start();
                Thread.sleep(3000);
                System.out.println("Interrupting thread");
                thread.interrupt(); // 线程并没有真正被中断,只是置了中断位
                Thread.sleep(3000);
                System.out.println("stopping application");
            } catch (InterruptedException e) {
                System.out.println("sleep interrupted");
                ;
            }
     
        }
     
        public void run() {
            while (!stop) {
                System.out.println("running");
                long time = System.currentTimeMillis();// 这样的操作,一直占用着CPU,非"阻塞",所以interrupt()对其无用,不生效.
                while (System.currentTimeMillis() - time < 1000) {
                    ;
                }
            }
            System.out.println("thread exiting under request..");
        }
     
    }

    http://wenku.baidu.com/view/1586ccea81c758f5f61f6751.html

    http://java.chinaitlab.com/base/786639.html

  • 相关阅读:
    MySQL慢查询日志总结
    SQL Server 关于列的权限控制
    Oracle global database name与db link的纠缠关系
    TCP Provider The semaphore timeout period has expired
    SQL SERVER 中如何用脚本管理作业
    Unable to determine if the owner (DomainUserName) of job JOB_NAME has server access
    TNS-12535: TNS:operation timed out案例解析
    ORA-12154 & TNS-03505 案例分享
    MS SQL巡检系列——检查数据库上一次DBCC CHECKDB的时间
    查看数据库表的数据量和SIZE大小的脚本修正
  • 原文地址:https://www.cnblogs.com/alipayhutu/p/2544889.html
Copyright © 2011-2022 走看看