Java如何让main线程不退出正确退出线程

没有更多推荐了,
不良信息举报
举报内容:
java多线程开发 如何正确关闭线程
举报原因:
原文地址:
原因补充:
最多只允许输入30个字
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!&nbsp>&nbsp
&nbsp>&nbsp
&nbsp>&nbsp
java线程安全退出
摘要:在多线程编程中,某些情况下,主线程需要等待子线程安全退出后,主线程在继续执行。为了实现这个效果,我借助Thread类isAlive()方法来实现。isAlive()方法是判断线程是否是活跃状态。以下是实现代码:classTest类是主线程。classProcessAccept类是子线程。线程类ProcessAccept:/***处理接入线程类**@authorAdministrator**/classProcessAcceptextendsThread{/***线程停止标志*
在多线程编程中,某些情况下,主线程需要等待子线程安全退出后,主线程在继续执行。
为了实现这个效果,我借助Thread类isAlive()方法来实现。
isAlive()方法是判断线程是否是活跃状态。
以下是实现代码:
class Test 类是主线程。
class ProcessAccept 类是子线程。
线程类 ProcessAccept :
/** * 处理接入线程类 * * @author Administrator * */ class ProcessAccept extends Thread { /** * 线程停止标志 */ private boolean stopRequested = /** * 同步锁 */ private ReentrantLock lock = new ReentrantLock(); /** * 向线程发送停止请求 */ public void stopRequest() { lock.lock(); // 设置停止标志为真 stopRequested = lock.unlock(); } /** * 获得当前停止标志 * * @return 前停止标志的值 */ private boolean getStopRequest() { boolean tempStopRequested = // 同步加锁lock.lock() lock.lock(); tempStopRequested = stopR // 同步解锁lock.unlock() lock.unlock(); return tempStopR } /** * 线程处理接入 */ public void run(){ while (true) { //判断停止标志 if (this.getStopRequest()){ } //此处处理业务逻辑 } }
调用类Test:
public class Test { ProcessAccept processAccept = new ProcessAccept(); public int stop(){ try { // 将线程的退出标志设置为真,处理未决连接请求 processAccept.stopRequest(); //等待线程安全退出后,再向下执行 while(processAccept.isAlive()){ try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } } catch (Exception e) { e.printStackTrace(); } } /** * @param args */ public static void main(String[] args) { Test t = Test(); //启动线程 t.processAccept.start(); //安全停止线程 t.stop(); }
以上是的内容,更多
的内容,请您使用右上方搜索功能获取相关信息。
若你要投稿、删除文章请联系邮箱:zixun-group@service.aliyun.com,工作人员会在五个工作日内给你回复。
云服务器 ECS
可弹性伸缩、安全稳定、简单易用
&40.8元/月起
预测未发生的攻击
&24元/月起
为您提供0门槛上云实践机会
你可能还喜欢
你可能感兴趣
阿里云教程中心为您免费提供
java线程安全退出相关信息,包括
的信息,所有java线程安全退出相关内容均不代表阿里云的意见!投稿删除文章请联系邮箱:zixun-group@service.aliyun.com,工作人员会在五个工作日内答复
售前咨询热线
支持与服务
资源和社区
关注阿里云
International博客分类:
摘自 http://my.oschina.net/reachwang/blog/296194
摘要  观察者模式:定义对象之间的一种一对多的依赖关系,当对象的状态发生改变时,所有依赖于它的对象都得到通知并且被自动更新。   观察者模式在JDK中有现成的实现,java.util.Obserable,如何进行监听线程,请看例子:
被监听的线程类:
package cn.std.
import java.util.O
import cn.std.util.DateU
public class RunThread extends Observableimplements Runnable{
publicvoid doBusiness(){
super.setChanged();
notifyObservers();
publicvoid run() {
while(true){
System.out.println("Runing- "+c+" "+DateUtil.getStdDateTime());
Thread.sleep(2000);
}catch (InterruptedException e) {
e.printStackTrace();
doBusiness();
if(c== 4){
Stringstr = null;
str.length();
}catch (Exception e) {
e.printStackTrace();
doBusiness();
publicstatic void main(String[] args) {
RunThreadrun = new RunThread();
Listener listen = new Listener();
un.addObserver(listen);
newThread(run).start();
被监听的线程需要继承Observable类,继承之后轻松变身为被观察者doBusiness方法,此处可以加上你的业务处理内容,接下来是Listener
package cn.std.
import java.util.O
import java.util.O
public class Listener implements Observer{
publicvoid update(Observable o, Object arg) {
System.out.println("RunThread死机");
RunThreadrun = new RunThread();
run.addObserver(this);
newThread(run).start();
System.out.println("RunThread重启");
很简单,只要实现Observer接口,实现其update方法,在方法内部重启线程
talentluke
浏览: 375191 次
来自: 深圳
分析的很好!但有一点:只要同步组合操作就可以了,不一定非要sy ...
core Java中有一段:Vector类对自己的所有可修改方 ...
基本上明白了.但执行顺是否应该是/etc/profile -& ...
各自有各自的场景吧楼主不要太激进了
写的不错,赞一个
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'http://blog.csdn.net/anhuidelinger/article/details/
终止线程的三种方法&
&&& 有三种方法可以使终止线程。&
&&& 1.& 使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。&
&&& 2.& 使用stop方法强行终止线程(这个方法不推荐使用,因为stop和suspend、resume一样,也可能发生不可预料的结果)。&
&&& 3.& 使用interrupt方法中断线程。&
1. 使用退出标志终止线程&
当run方法执行完后,线程就会退出。但有时run方法是永远不会结束的。如在服务端程序中使用线程进行监听客户端请求,或是其他的需要循环处理的任务。
在这种情况下,一般是将这些任务放在一个循环中,如while循环。如果想让循环永远运行下去,可以使用while(true){&&}来处理。但要想使
while循环在某一特定条件下退出,最直接的方法就是设一个boolean类型的标志,并通过设置这个标志为true或false来控制while循环
是否退出。下面给出了一个利用退出标志终止线程的例子。&
package chapter2;&
public class ThreadFlag extends Thread&
&&& public volatile boolean exit =&
&&& public void run()&
&&&&&&& while (!exit);&
&&& public static void main(String[] args) throws Exception&
&&&&&&& ThreadFlag thread = new ThreadFlag();&
&&&&&&& thread.start();&
&&&&&&& sleep(5000); // 主线程延迟5秒&
&&&&&&& thread.exit =& // 终止线程thread&
&&&&&&& thread.join();&
&&&&&&& System.out.println("线程退出!");&
在上面代码中定义了一个退出标志exit,当exit为true时,while循环退出,exit的默认值为false.在定义exit时,使用了一个
Java关键字volatile,这个关键字的目的是使exit同步,也就是说在同一时刻只能由一个线程来修改exit的值,&
&&& 2. 使用stop方法终止线程&
&&& 使用stop方法可以强行终止正在运行或挂起的线程。我们可以使用如下的代码来终止线程:&
thread.stop();&
&&& 虽然使用上面的代码可以终止线程,但使用stop方法是很危险的,就象突然关闭计算机电源,而不是按正常程序关机一样,可能会产生不可预料的结果,因此,并不推荐使用stop方法来终止线程。&
&&& 3. 使用interrupt方法终止线程&
&&& 使用interrupt方法来终端线程可分为两种情况:&
&&& (1)线程处于阻塞状态,如使用了sleep方法。&
&&& (2)使用while(!isInterrupted()){&&}来判断线程是否被中断。&
&&& 在第一种情况下使用interrupt方法,sleep方法将抛出一个InterruptedException例外,而在第二种情况下线程将直接退出。下面的代码演示了在第一种情况下使用interrupt方法。&
package chapter2;&
public class ThreadInterrupt extends Thread&
&&& public void run()&
&&&&&&& try&
&&&&&&& {&
&&&&&&&&&&& sleep(50000);& // 延迟50秒&
&&&&&&& }&
&&&&&&& catch (InterruptedException e)&
&&&&&&& {&
&&&&&&&&&&& System.out.println(e.getMessage());&
&&&&&&& }&
&&& public static void main(String[] args) throws Exception&
&&&&&&& Thread thread = new ThreadInterrupt();&
&&&&&&& thread.start();&
&&&&&&& System.out.println("在50秒之内按任意键中断线程!");&
&&&&&&& System.in.read();&
&&&&&&& thread.interrupt();&
&&&&&&& thread.join();&
&&&&&&& System.out.println("线程已经退出!");&
&&& 上面代码的运行结果如下:&
&&& 在50秒之内按任意键中断线程!&
&&& sleep interrupted&
&&& 线程已经退出!&
&&& 在调用interrupt方法后, sleep方法抛出异常,然后输出错误信息:sleep interrupted.&
注意:在Thread类中有两个方法可以判断线程是否通过interrupt方法被终止。一个是静态的方法interrupted(),一个是非静态的方
法isInterrupted(),这两个方法的区别是interrupted用来判断当前线是否被中断,而isInterrupted可以用来判断其他
线程是否被中断。因此,while
(!isInterrupted())也可以换成while (!Thread.interrupted())。&
如何停止java的线程一直是一个困恼我们开发多线程程序的一个问题。这个问题最终在Java5的中得到了回答:使用,让线程在run方法中停止。
在Java的多线程编程中,类型包含了一些列的方法,&,&&and&,&&and&。通过这些方法,我们可以对线程进行方便的操作,但是这些方法中,只有方法得到了保留。
在Sun公司的一篇文章《&》中详细讲解了舍弃这些方法的原因。那么,我们究竟应该如何停止线程呢?
建议使用的方法
在《&》中,建议使用如下的方法来停止线程:
&&&&private&volatile&T&
&&&&public&void&stop() {&
&&&&&&& blinker =&&
&&&&public&void&run() {&
&&&&&&& Thread thisThread = Thread.currentThread();&
&&&&&&&&while&(blinker == thisThread) {&
&&&&&&&&&&&&try&{&
&&&&&&&&&&&&&&& thisThread.sleep(interval);&
&&&&&&&&&&& }&catch&(InterruptedException e){&
&&&&&&&&&&& }&
&&&&&&&&&&& repaint();&
&&&&&&& }&
关于使用volatile关键字的原因,请查看。
当线程处于非运行(Run)状态
当线程处于下面的状况时,属于非运行状态:
当sleep方法被调用。
当wait方法被调用。
当被I/O阻塞,可能是文件或者网络等等。
当线程处于上述的状态时,使用前面介绍的方法就不可用了。这个时候,我们可以使用来打破阻塞的情况,如:
public void stop() {
Thread tmpBlinker =
if (tmpBlinker != null) {
tmpBlinker.interrupt();
当被调用的时候,将被抛出,所以你可以再run方法中捕获这个异常,让线程安全退出:
} catch (InterruptedException iex) {
throw new RuntimeException("Interrupted",iex);
当线程被I/O阻塞的时候,调用的情况是依赖与实际运行的平台的。在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 InputS
protected void processData(byte[] b, int n) { }
class ReaderClass extends Thread {
public void run( ) {
byte[] b = new byte[buflen];
while (!done) {
int n = is.read(b, 0, buflen);
processData(b, n);
} catch (IOException ioe) {
synchronized(lock) {
lock.notify( );
public InterruptibleReader(InputStream is) {
this(is, 512);
public InterruptibleReader(InputStream is, int len) {
public void run( ) {
ReaderClass rc = new ReaderClass( );
synchronized(lock) {
rc.start( );
while (!done) {
lock.wait( );
} catch (InterruptedException ie) {
rc.interrupt( );
is.close( );
} catch (IOException ioe) {}
另外,我们也可以使用接口。 实现了接口的类可以在阻塞的时候抛出。如:
package com.cnblogs.gpcuster
import java.io.BufferedR
import java.io.FileD
import java.io.FileInputS
import java.io.InputS
import java.io.InputStreamR
import java.nio.channels.C
public class InterruptInput {
static BufferedReader in = new BufferedReader(
new InputStreamReader(
Channels.newInputStream(
(new FileInputStream(FileDescriptor.in)).getChannel())));
public static void main(String args[]) {
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 =
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 =
public TimeOut() {
// interrupt thread that creates this TimeOut.
threadToInterrupt = Thread.currentThread();
setDaemon(true);
public void run() {
sleep(10000); // wait 10 sec
} catch(InterruptedException ex) {/*ignore*/}
threadToInterrupt.interrupt();
这里还需要注意一点,当线程处于写文件的状态时,调用不会中断线程。
不提倡的stop()方法&
臭名昭著的stop()停止线程的方法已不提倡使用了,原因是什么呢?
 当在一个线程对象上调用stop()方法时,这个线程对象所运行的线程就会立即停止,并抛出特殊的ThreadDeath()异常。这里的&立即&因为太&立即&了,
假如一个线程正在执行:
synchronized void {
  由于方法是同步的,多个线程访问时总能保证x,y被同时赋值,而如果一个线程正在执行到x = 3;时,被调用了 stop()方法,即使在同步块中,它也干脆地stop了,这样就产生了不完整的残废数据。而多线程编程中最最基础的条件要保证数据的完整性,所以请忘记 线程的stop方法,以后我们再也不要说&停止线程&了。
  &如何才能&结束&一个线程?
interupt()中断线程
一个线程从运行到真正的结束,应该有三个阶段:
处理结束前的工作,也就是准备结束.
那么如何让一
个线程结束呢?既然不能调用stop,可用的只的interrupt()方法。但interrupt()方法只是改变了线程的运行状态,如何让它退出运
行?对于一般逻辑,只要线程状态已经中断,我们就可以让它退出,这里我们定义一个线程类ThreadA,所以这样的语句可以保证线程在中断后就能结束运
,一个测试类,ThreadDemo
  这样ThreadDemo调用interrupt()方法,isInterrupted()为true,就会退出运行。但是如果线程正在执行wait,sleep,join方法,你调用interrupt()方法,这个逻辑就不完全了。
我们可以这样处理:
想一想,如果
一个正在sleep的线程,在调用interrupt后,会如何?wait方法检查到isInterrupted()为true,抛出异常,
而你又没有处理。而一个抛出了InterruptedException的线程的状态马上就会被置为非中断状态,如果catch语句没有处理异常,则下一
次循环中isInterrupted()为false,线程会继续执行,可能你N次抛出异常,也无法让线程停止。
这个错误情况的实例代码
public&class&ThreadA&extends&Thread&{
&&&int&count=0;
&&&public&void&run(){
&&&&&&&System.out.println(getName()+"将要运行...");
&&&&&&&while(!this.isInterrupted()){
&&&&&&&&&&&System.out.println(getName()+"运行中"+count++);
&&&&&&&&&&&try{
&&&&&&&&&&&&&&&Thread.sleep(400);
&&&&&&&&&&&}catch(InterruptedException&e){
&&&&&&&&&&&&&&&System.out.println(getName()+"从阻塞中退出...");
&&&&&&&&&&&&&&&System.out.println("this.isInterrupted()="+this.isInterrupted());
&&&&&&&&&&&}
&&&&&&&System.out.println(getName()+"已经终止!");
ThreadDemo
public&class&ThreadDemo&{
&&&&public&static&void&main(String&argv[])throws&InterruptedException{
&&&&&&&&ThreadA&ta=new&ThreadA();
&&&&&&&&ta.setName("ThreadA");
&&&&&&&&ta.start();
&&&&&&&&Thread.sleep(2000);
&&&&&&&&System.out.println(ta.getName()+"正在被中断...");
&&&&&&&&ta.interrupt();
&&&&&&&&System.out.println("ta.isInterrupted()="+ta.isInterrupted());
 那么如何能
确保线程真正停止?在线程同步的时候我们有一个叫&二次惰性检测&(double
check),能在提高效率的基础上又确保线程真正中同步控制中。那么我把线程正确退出的方法称为&双重安全退出&,即不以isInterrupted
()为循环条件。而以一个标记作为循环条件:
正确的ThreadA代码是:
public&class&ThreadA&extends&Thread&{
&&&&private&boolean&isInterrupted=
&&&int&count=0;
&&&public&void&interrupt(){
&&&&&&&isInterrupted&=&
&&&&&&&super.interrupt();
&&&public&void&run(){
&&&&&&&System.out.println(getName()+"将要运行...");
&&&&&&&while(!isInterrupted){
&&&&&&&&&&&System.out.println(getName()+"运行中"+count++);
&&&&&&&&&&&try{
&&&&&&&&&&&&&&&Thread.sleep(400);
&&&&&&&&&&&}catch(InterruptedException&e){
&&&&&&&&&&&&&&&System.out.println(getName()+"从阻塞中退出...");
&&&&&&&&&&&&&&&System.out.println("this.isInterrupted()="+this.isInterrupted());
&&&&&&&&&&&}
&&&&&&&System.out.println(getName()+"已经终止!");
1 处于运行状态的线程停止
&&&&&&& 处于运行状态的线程就是常见的处于一个循环中不断执行业务流程的线程,这样的线程需要通过设置停止变量的方式,在每次循环开始处判断变量是否改变为停止,以达到停止线程的目的,比如如下代码框架:
&&&&&&& 如果主线程调用该线程对象的
&&&&&&& 上述的
2 即将或正在处于非运行态的线程停止
&&&&&&& 线程的非运行状态常见的有如下两种情况:
可中断等待:线程调用了
2.1 处于可中断等待线程的停止
&&&&&&& 如果线程调用了可中断等待方法,正处于等待状态,则可以通过调用
&&&&&&& 上述的
&&&&&&&& 特别的,
&&&&&&& 需要注意的是
2.2 处于IO阻塞状态线程的停止
&&&&&&& 以文件
&&&&&&&& 实现
&&&&&&& 虽然解除
3 处于大数据IO读写中的线程停止
&&&&&&&& 处于大数据
&&&&&&& 最好的建议是将大数据的
4 在线程运行前停止线程
&&&&&&&& 有时,线程中的
&&&&&&&& 为了解决这个问题,不得不自己再额外创建一个
&&&&&&&& 还有一种解决方法,也可以在
5 参考资料
阅读(...) 评论()Java线程停止方法之Interrupt方法_Linux编程_Linux公社-Linux系统门户网站
你好,游客
Java线程停止方法之Interrupt方法
来源:Linux社区&
作者:JcWft
最近在学习Java多线程相关的知识点,其中关于线程停止的方法网上也有不少大牛给出了详细的解答,而我这边就其中Interrupt方法的注意点给自己提个醒。
  首先还是大概的罗列下停止线程的方法:
  1、使用stop()方法等,不过已经不再被推荐使用,和suspend、resume一样。
  2、使用退出标志终止线程,引入一个共享变量,volatile类型或者使用synchronized来监视共享变量相关操作的方法,然后在run()方法中,通过while循环不停的轮询这个标志。
  3、使用Interrupt方法中断线程。
  注意点:我一开始看到该方法的时候,认为interrupt会使线程停止运行,但事实上并非如此,调用一个线程的Interrupt方法会把线程的状态改为中断态。这其中又可以细分成两个方面:
  1)对于因执行了sleep、wait、join方法而休眠的线程:调用Interrupt方法会使他们不再休眠,同时会抛出 InterruptedException异常。比如一个线程A正在sleep中,这时候另外一个程序里去调用A的interrupt方法,这时就会迫使A停止休眠而抛出InterruptedException异常,从而提前使线程逃离阻塞状态。
  2)对于正在运行的线程,即没有阻塞的线程,调用Interrupt方法就只是把线程A的状态改为interruptted,但是不会影响线程A的继续执行。
以下是对处于阻塞状态线程使用Interrupt方法的例子:
class MyThread extends Thread {& & & volatile boolean stop =& & & public static void main( String args[] ) throws Exception {& & & & & MyThread thread = new MyThread();& & & & & System.out.println( "Starting thread..." );& & & & & thread.start();& & & & & Thread.sleep( 3000 );& & & & & System.out.println( "hread stop..." );& & & & & thread.stop =& //如果线程阻塞,将不会检查此变量& & & & & thread.interrupt();& & & & & Thread.sleep( 3000 );& & & & & System.out.println( "end..." );& & & }& & & & public void run() {& & & & & while ( !stop ) {& & & & & & &
System.out.println( "Thread running..." );& & & & & & &
try {& & & & & & & & &
Thread.sleep( 1000 );& & & & & & &
} catch ( InterruptedException e ) {& & & & & & & & &
System.out.println( "Thread interrupted..." );& & & & & & &
}& & & & & }& & & & & System.out.println( "Thread exiting under request..." );& & & }& }
说明:对于被上述几种方法阻塞的线程,正确的停止线程方式是设置共享变量,并调用interrupt()(注意变量应该先设置)。设置共享变量是为了没有被阻塞的线程也能正常退出。
  以下内容还在继续研究中
  在看一些博主的文章时还看到了一些特殊情况,也在这边做个补充:
  线程在I/O操作进行时被阻塞
  分两种情况:
  1)使用通道(channels)的情况,通道是Java 1.4引入的I/O API,被阻塞的线程将收到一个ClosedByInterruptException异常。这与使用Interrupt方法抛出异常的用法一样,只是异常不同而已。
  2)使用传统的I/O。
  说明:即使Interrupt方法被调用了,Thread.interrupt()也不起作用,因为线程将不会退出被阻塞状态。
  解决办法:调用阻塞该线程的套接字的close()方法。在这种情形下,如果线程被I/O操作阻塞,该线程将接收到一个SocketException异常,这与使用interrupt()方法引起一个InterruptedException异常被抛出非常相似。
  注意:唯一要说明的是,必须存在socket的引用(reference),只有这样close()方法才能被调用。这意味着socket对象必须被共享。
  以下代码供参考:
class MyThread extends Thread {& & & volatile boolean stop =& & & volatile ServerS&
& & public static void main( String args[] ) throws Exception {& & & & & MyThread thread = new MyThread();& & & & & System.out.println( "Starting thread..." );& & & & & thread.start();& & & & & Thread.sleep( 3000 );& & & & & System.out.println( "Asking thread to stop..." );& & & & & thread.stop =& & & & & thread.socket.close();& & & & & Thread.sleep( 3000 );& & & & & System.out.println( "Stopping application..." );& & & &
} && & public void run() {& & & & & try {& & & & & & & socket = new ServerSocket(7856);& & & & & } catch ( IOException e ) {& & & & & & & System.out.println( "Could not create the socket..." );& & & & & & && & & & & }& & & & & while ( !stop ) {& & & & & & & System.out.println( "Waiting for connection..." );& & & & & & & try {& & & & & & & & & Socket sock = socket.accept();& & & & & & & } catch ( IOException e ) {& & & & & & & & & System.out.println( "accept() failed or interrupted..." );& & & & & & & }& & & & & }& & & & & System.out.println( "Thread exiting under request..." );& & & }& }
以上是自己对停止线程方法的一些总结,当然也是借鉴了不少博主的分享。重点放在了Interrupt方法,因为这边容易理解出错!
本文永久更新链接地址:
相关资讯 & & &
& (01月05日)
& (10/23/:12)
& (01月26日)
& (10/25/:34)
& (07/20/:20)
   同意评论声明
   发表
尊重网上道德,遵守中华人民共和国的各项有关法律法规
承担一切因您的行为而直接或间接导致的民事或刑事法律责任
本站管理人员有权保留或删除其管辖留言中的任意内容
本站有权在网站内转载或引用您的评论
参与本评论即表明您已经阅读并接受上述条款

我要回帖

更多关于 线程如何退出结束 的文章

 

随机推荐