zoukankan      html  css  js  c++  java
  • 如何停止JAVA线程

      如何停止java的线程一直是一个困恼我们开发多线程程序的一个问题。这个问题最终在Java5的java.util.concurrent中得到了回答:使用interrupt(),让线程在run方法中停止。

    简介

      在Java的多线程编程中,java.lang.Thread类型包含了一些列的方法start(), stop(), stop(Throwable) and suspend(), destroy() and resume()。通过这些方法,我们可以对线程进行方便的操作,但是这些方法中,只有start()方法得到了保留。

      在Sun公司的一篇文章《Why are Thread.stop, Thread.suspend and Thread.resume Deprecated? 》中详细讲解了舍弃这些方法的原因。那么,我们究竟应该如何停止线程呢?

    建议使用的方法

      在《Why are Thread.stop, Thread.suspend and Thread.resume Deprecated? 》中,建议使用如下的方法来停止线程:

        private volatile Thread blinker; 

        public void stop() { 

            blinker = null; 

        } 

        public void run() { 

            Thread thisThread = Thread.currentThread(); 

            while (blinker == thisThread) { 

                try { 

                    thisThread.sleep(interval); 

                } catch (InterruptedException e){ 

                } 

                repaint(); 

            } 

        }

    关于使用volatile关键字的原因,请查看http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#36930。

    当线程处于非运行(Run)状态

    当线程处于下面的状况时,属于非运行状态:

    当sleep方法被调用。

    当wait方法被调用。

    当被I/O阻塞,可能是文件或者网络等等。

    当线程处于上述的状态时,使用前面介绍的方法就不可用了。这个时候,我们可以使用interrupt()来打破阻塞的情况,如:

    public void stop() {

            Thread tmpBlinker = blinker;

            blinker = null;

            if (tmpBlinker != null) {

               tmpBlinker.interrupt();

            }

        }

    当interrupt()被调用的时候,InterruptedException将被抛出,所以你可以再run方法中捕获这个异常,让线程安全退出:

    try {

       ....

       wait();

    } catch (InterruptedException iex) {

       throw new RuntimeException("Interrupted",iex);

    }

    阻塞的I/O

    当线程被I/O阻塞的时候,调用interrupt()的情况是依赖与实际运行的平台的。在Solaris和Linux平台上将会抛出InterruptedIOException的异常,但是Windows上面不会有这种异常。所以,我们处理这种问题不能依靠于平台的实现。如:

    package com.cnblogs.gpcuster

    import java.net.*;

    import java.io.*;

    public abstract class InterruptibleReader extends Thread {

        private Object lock = new Object( );

        private InputStream is;

        private boolean done;

        private int buflen;

        protected void processData(byte[] b, int n) { }

        class ReaderClass extends Thread {

            public void run( ) {

                byte[] b = new byte[buflen];

                while (!done) {

                    try {

                        int n = is.read(b, 0, buflen);

                        processData(b, n);

                    } catch (IOException ioe) {

                        done = true;

                    }

                }

                synchronized(lock) {

                    lock.notify( );

                }

            }

        }

        public InterruptibleReader(InputStream is) {

            this(is, 512);

        }

        public InterruptibleReader(InputStream is, int len) {

            this.is = is;

            buflen = len;

        }

        public void run( ) {

            ReaderClass rc = new ReaderClass( );

            synchronized(lock) {

                rc.start( );

                while (!done) {

                    try {

                        lock.wait( );

                    } catch (InterruptedException ie) {

                        done = true;

                        rc.interrupt( );

                        try {

                            is.close( );

                        } catch (IOException ioe) {}

                    }

                }

            }

        }

    }

    另外,我们也可以使用InterruptibleChannel接口。 实现了InterruptibleChannel接口的类可以在阻塞的时候抛出ClosedByInterruptException。如:

    package com.cnblogs.gpcuster

    import java.io.BufferedReader;

    import java.io.FileDescriptor;

    import java.io.FileInputStream;

    import java.io.InputStream;

    import java.io.InputStreamReader;

    import java.nio.channels.Channels;

    public class InterruptInput {   

        static BufferedReader in = new BufferedReader(

                new InputStreamReader(

                Channels.newInputStream(

                (new FileInputStream(FileDescriptor.in)).getChannel())));

        

        public static void main(String args[]) {

            try {

                System.out.println("Enter lines of input (user ctrl+Z Enter to terminate):");

                System.out.println("(Input thread will be interrupted in 10 sec.)");

                // interrupt input in 10 sec

                (new TimeOut()).start();

                String line = null;

                while ((line = in.readLine()) != null) {

                    System.out.println("Read line:'"+line+"'");

                }

            } catch (Exception ex) {

                System.out.println(ex.toString()); // printStackTrace();

            }

        }

        

        public static class TimeOut extends Thread {

            int sleepTime = 10000;

            Thread threadToInterrupt = null;    

            public TimeOut() {

                // interrupt thread that creates this TimeOut.

                threadToInterrupt = Thread.currentThread();

                setDaemon(true);

            }

            

            public void run() {

                try {

                    sleep(10000); // wait 10 sec

                } catch(InterruptedException ex) {}

                threadToInterrupt.interrupt();

            }

        }

    }



  • 相关阅读:
    开放源码的对象关系映射工具ORM.NET 插入数据 Insert/Update Data
    开放源码的对象关系映射工具ORM.NET 快档开发入门 Quick Start
    .NET 动态脚本语言Script.NET 开发指南
    开放源码的对象关系映射工具ORM.NET 删除数据 Deleting Records using ORM.NET
    .NET Remoting过时了吗?为什么公司的项目还是选择用.NET Remoting,而不是WCF?
    开放源码的对象关系映射工具ORM.NET 查看和显示数据 View and Display data using ORM.NET
    开放源码的对象关系映射工具ORM.NET 查询表 调用存储过程 增加自定义代码
    技术人生:坚持,每日一博
    CQRS:CQRS + DDD + MDP 实现快速应用程序开发
    NodeJs:Happy代码生成器,重构了代码,更新了文档,完善了示例,欢迎下载使用
  • 原文地址:https://www.cnblogs.com/luckForever/p/7254215.html
Copyright © 2011-2022 走看看