精华内容
下载资源
问答
  • 如何正确地结束一个线程

    千次阅读 2019-01-02 00:19:25
    一般来说,当一个线程的方法体执行完,这个方法就会结束了。我们一般不直接使用stop方法来终止线程,这可能会导致业务逻辑不完整或者破坏原子性的操作,一段代码可能用来输出某些重要的信息,在方法的执行中使用stop...

    为什么不用stop()方法

    一般来说,当一个线程的方法体执行完,这个方法就会结束了。我们一般不直接使用stop方法来终止线程,这可能会导致业务逻辑不完整或者破坏原子性的操作,一段代码可能用来输出某些重要的信息,在方法的执行中使用stop方法终止线程,会使得输出的信息破坏或者不完整;在原子操作比如重入锁的使用时,当一个线程对象多次获得锁会使得计数加一,接下来需要以相同的次数释放锁直到计数减到0,别的线程才能获得锁资源,这种操作是原子性的,因为对线程来说,他们拿到锁和最终释放锁时计数都是为0的,因此这是一种原子性操作,假设在一个对象使用锁的期间,使用stop方法强行终止线程,这会导致锁的计数不为0,即破坏了原子性操作。综合来说,我们如果要正确地终止一个线程,不应该使用stop()这种过时的方法。
    比较常用的是以下两种方法:
    1、使用while循环轮询标志位,为false则退出循环,结束方法体,终止线程。
    2、使用interrupt()方法在线程阻塞状态下结束线程。

    方法1:使用标志位

    这种方法是我尝试终止线程时最初采用的方法,使用起来很方便,原理也很简单,只要在while循环里持续判断一个Boolean变量的值就可以了,一旦满足离开循环的条件,那么就可以离开线程的方法体,结束线程。
    1、代码实现

    public class Test {
            boolean flag=true;
    	    public static void main(String[] args){
    	    	Test test = new Test();
    	    	test.demo();
    	    }	
    	    public void demo(){
    	    	Thread t1 = new Thread(){	    		
    		    		public void run()  //重写run方法
    		    		{
    		    			while(flag==true)  
    		    			{
    		    				System.out.println("线程在执行");	    		
    		    			}
    		    			System.out.println("线程结束了。。。。。。。。");
    		    		}		
    	    	};	    	
    	    	t1.start();
    	    	try {
    				Thread.sleep(10);
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
                flag=false;
    	    }	
    }
    

    2、运行结果

    线程在执行
    线程在执行
    线程在执行
    线程在执行
    线程在执行
    线程在执行
    线程在执行
    线程在执行
    线程结束了。。。。。。。。
    

    3、分析:我们先创建一个线程并运行它,在while循环里不断输出“线程在执行”,然后我们修改标志位为false,离开循环并结束了线程。

    方法2:使用Interrupt方法(中断)

    使用中断的方法可以正确结束一个线程。
    使用到的API介绍:
    1、interrupt()方法:对某个线程对象调用这个方法就可以把它的中断标志位置为true,但它不能立刻结束一个线程。
    2、currentThread()方法:静态方法,用线程类调用获得当前线程对象的引用。
    4、sleep():使当前线程睡眠,释放资源但是不释放锁。
    5、join():等待线程终止,停住调用这个方法的当前线程,等待指定的线程运行结束。减少程序运行的不确定性。
    6、start():启动一个线程。
    7、interrupted()方法:是静态方法,测试当前线程是否被中断,同时清除中断标志。也就是说,在中断标志置位后第一次调用返回true,第二次调用返回false。
    8、isinterrupt()方法:这个方法由对象调用,测试线程是否已经被中断,仅仅返回标志的状态,不会对标志有任何影响。
    轮询中断标志退出线程:
    思路:
    main方法中新建并启动线程,然后延时一段时间,置位子线程的中断标志。子线程检测到中断标志被置位,则离开循环,结束线程。
    代码:

    public class Test {
    	    public static void main(String[] args){
    	    	Test test = new Test();
    	    	test.demo();
    	    }	
    	    public void demo(){
    	    	Thread tt = new Thread()
    			{		
    	    		public void run() {
    	    			int add=0;  //记录循环次数
    	    			System.out.println("线程开始");
        			      while(true)
        			      {
        			    	if(this.isInterrupted())
        			    		break;
        			    	add++;
    	    				System.out.println("执行次数:"+add);
        			      } 
        			      System.out.println("线程结束");
    	    		}    			    			    		
    			};    	
    	    	tt.start();
                try {
    				Thread.sleep(5);
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    	    	tt.interrupt();	    	
    	    }	
    }
    

    运行结果:
    在这里插入图片描述
    子线程主动抛异常,并捕获,结束线程(解决上述方案在break后还会执行后续代码的问题)
    思路:
    子线程try,catch代码块,准备捕获中断异常。子线程在检测到中断标志后,主动throw一个异常,被捕获并执行捕获处理程序,结束线程。
    代码:

    public class Test {
    	    public static void main(String[] args){
    	    	Test test = new Test();
    	    	test.demo();
    	    }	
    	    public void demo(){
    	    	Thread tt = new Thread()
    			{		
    	    		public void run() {
    	    			int add=0;  //记录循环次数
    	    			System.out.println("线程开始");
    	    			try{
        			      while(true){    			    	  
    	    			    	if(this.isInterrupted()){
    	    			    		System.out.println("检测到中断标志为true,抛一个异常");
    	    			    		throw new InterruptedException();
    	    			    	}
    	    			    	add++;
    		    				System.out.println("执行次数:"+add);    			    	  
        			      } 
    	    			}catch(InterruptedException e){
        			    		  System.out.println("接收到了抛出的异常,直接结束线程");
        			    		  e.printStackTrace();
        			    }
    	    		}    			    			    		
    			};    	
    	    	tt.start();
                try {
    				Thread.sleep(5);
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    	    	tt.interrupt();	    	
    	    }	
    }
    

    运行结果:
    在这里插入图片描述
    在线程睡眠时置位中断标志:
    思路:
    新建、运行线程并让其睡眠,然后在main方法中把中断标志置为true,子线程在睡眠中会不断查询这个标志,检测到标志为true则抛出一个中断异常,结束线程。若把sleep换为join,效果相同(都是陷入阻塞状态)。
    代码:

    public class Test {
    	    public static void main(String[] args){
    	    	Test test = new Test();
    	    	test.demo();
    	    }	
    	    public void demo(){
    	    	Thread tt = new Thread(){		
    	    		public void run() {
    	    			System.out.println("线程开始");
    	    			try{
        			      sleep(3000);
    	    			}catch(InterruptedException e){
    	    				System.out.println("捕获到了一个中断异常");
    	    				System.out.println("线程结束");
    	    				e.printStackTrace();
    	    			}	    			
    	    		}    			    			    		
    			};    	
    	    	tt.start();
                try {
    				Thread.sleep(50);
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    	    	tt.interrupt();	    	
    	    }	
    }
    

    运行结果:
    在这里插入图片描述

    展开全文
  • 如何强制结束一个线程

    千次阅读 2013-01-08 21:27:42
    书上给出了一个例子,以后强制结束一个线程就靠它了。 程序片段: //线程退出事件 HANDLE hExitEvent = null ; //一个需要长时间运行的线程 DWORD WINAPI ThreadFun ( LPVOID p ) {  for ( int I =0

    WIN32多线程程序设计学习笔记(第四章 下 第五章)(原文名)

    那么如何强制结束一个线程?书上给出了一个例子,以后强制结束一个线程就靠它了。

    程序片段:

    //线程退出事件

    HANDLE hExitEvent = null ;

    //一个需要长时间运行的线程

    DWORD WINAPI ThreadFun ( LPVOID p )

    {

           for (  int I =0 ; I < 1000000; I++ )

           {

           //判断线程是否要被强制结束

    /*  可能在这里大家有点疑惑,如果没有调用SetEvent()的方法,

    hExitEvent不是总处于未激发状态吗?哪线程不就停在这里不动了?

    答案是:这里用到了P74提到的一个Wait….()一个用法,当time_out

    0,检查hExitEvent的状态,如果hExitEvent处于未激发状态,

    立刻返回WAIT_TIMEOUT,如果hExitEvent处于激发状态,则立刻

    返回WAIT_OBJECT_0*/

    if ( WaitForSingleObject ( hExitEvent , 0 ) !=WAIT_TIMEOUT )

    {

           //做一些退出线程前的清理工作

           return (DWORD) –1 ;

    }

                  //做一些极其消耗时间的处理….

                  //…….

                  //……..

           }

    }

    void main()

    {            

                  HANDLE hThrd;

    //构造EVENT核心对象,初始状态处于未激发状态,Manual方式

                  hExitEvent = CreateEvent ( NULL,TRUE,FALSE,NULL ) ;

    //线程启动

                  hThrd  = CreateThread ( null,ThreadFun,…..);

                  //等待了很久,实在等不下去了,发出结束线程退出事件(激发EVENT核心对象)

                  //迫使线程结束

                  SetEvent ( hExitEvent ) ;

           //等待线程结束

           WaitForSingleObject (hThrd,… );

           CloseHandle ( hThrd );

    }

    展开全文
  • 一个线程通知另外一个线程结束

    千次阅读 2018-04-03 15:31:42
    有一道面试题, 有一个集合,一个线程t1往里面加元素,当集合的size为5的时候,让t2线程结束;三种实现方法:方法一: 使用volatilepackage thread; import java.util.ArrayList; import java.util.List; /** * Created ...

    有一道面试题, 有一个集合,一个线程t1往里面加元素,当集合的size为5的时候,让t2线程结束;

    三种实现方法:

    方法一: 使用volatile

    package thread;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * Created by ZWZS on 2018/4/3.
     * 有一个list,一个线程往里面添加元素,当list.size()长度为5的时候,通知线程2,让线程2结束
     * 第一种方式,使用volatile来实现,使用volatile时,线程t2,一直处于while(true),比较消耗性能
     * 可以采用 wait()和notify()优化
     */
    public class NotifyStop {
        private volatile static List<String> list = new ArrayList<>();
    
        public void add(String s) {
            list.add(s);
            System.out.println(Thread.currentThread().getName() + " " + s);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        public void get() {
            while (true) {
                if (list.size() == 5) {
                    System.out.println("t2结束");
                    return;
                }
            }
        }
    
        public static void main(String[] args) {
            NotifyStop notifyStop = new NotifyStop();
            new Thread(() -> {
                for (int i = 0; i < 10; i++) {
                    notifyStop.add("abc");
                }
            }, "t1").start();
    
            new Thread(() -> {
                notifyStop.get();
            }, "t2").start();
    
        }
    
    }

    使用voltaile时,线程t2处于while(true)循环中,比较消耗性能,可以让集合的size()等于5的时候再执行.引申出第二种方法;

        第二种方法: 使用wait()和notify();

    package thread;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.TimeUnit;
    
    /**
     * Created by ZWZS on 2018/4/3.
     * 有一个list,一个线程往里面添加元素,当list.size()长度为5的时候,通知线程2,让线程2结束
     * 第二种方式,使用wait()和notify()来优化
     * 可以采用 wait()和notify()优化
     */
    public class NotifyStop2 {
        private static List<String> list = new ArrayList<>();
    
        private final Object lock = new Object();
    
        public void add(String s) {
            synchronized (lock) {
                list.add(s);
                System.out.println(Thread.currentThread().getName() + " " + s);
                try {
                    TimeUnit.MILLISECONDS.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
                if (list.size() == 5) {
                    lock.notify();
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
    
        }
    
        public void get() {
            synchronized (lock) {
                if (list.size() != 5) {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("t2结束");
                lock.notify();
            }
    
    
        }
    
        public static void main(String[] args) {
            NotifyStop2 notifyStop2 = new NotifyStop2(); //特别注意使用同一个对象进行调用
            new Thread(() -> {
                for (int i = 0; i < 10; i++) {
                    notifyStop2.add("abc");
                }
            }, "t1").start();
    
            new Thread(() -> {
                notifyStop2.get();
            }, "t2").start();
    
        }
    
    }

    第三种方法: 使用CountdownLatch,线程2首先await(),当countdownLatch执行一次countdown时,线程2就执行一次.

    package thread;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.TimeUnit;
    
    /**
     * Created by ZWZS on 2018/4/3.
     * 有一个list,一个线程往里面添加元素,当list.size()长度为5的时候,通知线程2,让线程2结束
     * 第三种方式,使用countdownLatch来搞定
     */
    public class NotifyStop3 {
        private static List<String> list = new ArrayList<>();
    
        private final CountDownLatch countDownLatch = new CountDownLatch(1);
    
        public void add(String s) {
            list.add(s);
            System.out.println(Thread.currentThread().getName() + " " + s);
            if (list.size() == 5) {
                countDownLatch.countDown();
            }
            try {
                TimeUnit.MILLISECONDS.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
        }
    
        public void get() {
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (list.size() == 5) {
    
                System.out.println("t2收到通知");
            }
        }
    
    
        public static void main(String[] args) {
            NotifyStop3 notifyStop3 = new NotifyStop3(); //特别注意使用同一个对象进行调用
            new Thread(() -> {
                for (int i = 0; i < 10; i++) {
                    notifyStop3.add("abc");
                }
            }, "t1").start();
    
            new Thread(() -> {
                notifyStop3.get();
            }, "t2").start();
    
        }
    
    }

    使用wait()和notify()时,要注意wait()会释放锁,而notify()不会释放锁,推荐使用countdownLatch.

    展开全文
  • 如何立即结束一个线程

    千次阅读 2016-03-11 23:44:50
    如何立即结束一个线程? 本文是作者在实际经验中的心得与体会,开发环境为苹果系统。如果有更好的方式请留言,高手请忽略。转载请注明作者以及出处。 背景平时开发中经常会有这么个需求:实现在线程中循环执行一些...

    如何立即结束一个线程?

    本文是作者在实际经验中的心得与体会,开发环境为苹果系统。如果有更好的方式请留言,高手请忽略。转载请注明作者以及出处。


    背景

    平时开发中经常会有这么个需求:实现在线程中循环执行一些指令,每次循环间隔n秒。那么问题来了,如何能够做到立即结束这个线程?我目前只用GCD,有人可能会说用dispatch_suspend(),这个方法必须和dispatch_resume()成对使用,而且suspend后线程只是暂停而已,并没有释放资源。如果用dispatch_release(),且不说ARC下无法使用这个方法,如果强制释放正在运行的线程资源,程序会直接crash。所以目前在GCD中我也没找到好的方法,要么是我理解不透彻不会用。

    第一招

    最初的做法是在每次循环时判断一个标志位(bool),如果为false就停止循环,线程随即结束。但是这样带来的一个问题是由于循环每次都要间隔几秒,sleep一下,会导致线程无法立即结束,最长会有那n秒的延迟,这显然不是我所希望看到的。

    dispatch_async(dispatch_get_global_queue(0,0), ^(){
        while(running) {
            // do something
            sleep(5);
        }
    });

    第二招

    既然有几秒钟延迟,那就把休眠时间拆分:

    dispatch_async(queue, ^(){
        while(running) {
            // do something
            sleep(1); if(!running){break;}
            sleep(1); if(!running){break;}
            sleep(1); if(!running){break;}
            sleep(1); if(!running){break;}
            sleep(1); if(!running){break;}
        }
    });

    这样做不够优雅,只是把延迟时间缩短而已,还是会有1秒钟的延迟。

    第三招

    假如还有这样的需求:我不光要能够立即结束线程,还能再次启动它,做到随心所欲的控制。这个是目前能想到的还算满意的方法,把上述启动线程的逻辑做成2个单例,第一次执行时,使用第一个单例;第二次执行时判断如果第一个单例在执行,则结束它,执行第二个单例。这样就不必等第一个线程结束,直接再开一个线程。如果再执行,则最多只会同时出现两个线程而已。

    @implement MYClass
    
    + (id)shareInstance1 {
        ...
    }
    
    + (id)shareInstance2 {
        ...
    }
    
    + (void)func {
        MYClass *obj = [MYClass shareInstance1];
        if (obj.idle) {
            [obj begin];
            MYClass *obj2 = [MYClass shareInstance2];
            if (!obj2.idle) {
                [obj2 end];
            }
        }
        else {
            [obj end];
            MYClass *obj2 = [MYClass shareInstance2];
            [obj2 begin];
        }
    }
    
    - (void)begin {
        idle = NO;
        dispatch_async(queue, ^(){
            while(running) {
                ...
            }
            idle = YES;
        });
    }
    
    - (void)end {
        running = NO;
    }
    
    @end

    以上就是我目前能想到的思路,如有更好的方案请告诉我。

    展开全文
  • 在Java中停止一个线程有三种办法: 1.正常结束执行; 2.发生异常; 3.被其他线程stop(Java官方不建议) 参考:...
  • QT如何结束一个线程

    2012-03-08 11:15:23
    从QObject继承一个类,将线程需要实现的功能...我需要结束线程以释放资源,但是线程貌似还在exec()中,不会自动结束,但是我使用quit(),或者exit(0),或者terminate(),都出现程序崩溃,不知道该如何正常结束一个线程。
  • 一个线程创建另一个线程

    千次阅读 2017-02-20 17:39:54
    线程是不分父子线程的,一个线程创建另一个线程,尽管第一个线程已经结束,第二个线程还是可以照常运行
  • Win32线程——等待另一个线程结束

    千次阅读 2016-12-14 21:14:12
    如果你没有等待线程结束就莽撞地结束程序,线程会被系统强制结束掉——在它完成它的工作之前。 由于让线程停工是操作系统的责任,很合理地我们会认为操作系统也有责任让其他线程知道某个线程停工了。 Sleep()这...
  • HANDLE g_hThread = NULL;   DWORD dw = WaitForSingleObject(g_hThread, 0);...//线程正在运行 {  TerminateThread(g_hThread, dwExitCode);  //不建议强制结束    if(g_hThread !=
  • 一个脚本文件中,如果有多个线程组,并且想让他们从上到下依次执行,只需在测试计划页面,勾选“独立运行每个线程组”即可
  • 强制结束一个线程 VOID ExitThread( DWORD dwExitCode //in,打定此线程被强制结束后,线程返回的值); 说明:线程中,放在此函数之后的任何代码,不会被执行 程序启动后就执行的那个线程称 主线程,主线程,必须负责...
  • 一个activity,包含两个fragment,两个fragment各自包含一个死循环线程,我想通过一个fragment结束这个activity(通过finish),顺便把这个fragment里的死循环线程结束了(通过flag=false和thread.interrupt())。...
  • 线程是你在Android中避不开的一个话题。 因为Android后期版本对主线程不允许运行耗时操作的规定,你新开线程的...设置一个标志位,当你想要结束线程的时候,就把这个标志位的状态改变。 直接看代码,更容易理解:
  • 强制结束另外一个线程的办法

    千次阅读 2009-01-08 17:07:00
    首先使用AfxBeginThread()函数建立起一个线程,该函数返回了一个CWinThread指针,设返回的指针变量为:pThread,那么强制关闭这个线程为: DWORD ExitCode; GetExitCodeThread(pThread->m_hThread, &ExitCode);...
  • 我遇到了这样的问题,线程1 是一个事件的执行方法,可能不停的调用线程2 是一个弹出OK按钮,表明已经执行完毕只需要这么写,把Thread定义在类里面,而不是方法里面,这样在线程2里面就可以访问到线程1Thread sh;...
  • 有时开启一个线程是为了把耗时的操作转移到线程中执行,主进程中可以执行其它的任务,避免了因为大量的重复性操作导致主进程阻塞。 控制线程暂停的方法: 线程的同步用到了QMutex类,作为一个互斥锁控制进行保护。...
  • 利用GCD并行多线程并且等待所有线程结束之后再执行其它任务 dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, ...// 并行执行的线程一 }); dispatch_group_async(group, dispatc
  • 因为界面相当于开了一个线程我们默认为线程A,计时器倒计时的线程线程B 线程A负责监听界面的事件,以此来决定线程B的执行和终止 方案一:线程A中监听到事件直接调用线程B,此时线程A会挂起,整个界面需要等线程B...
  • 线程结束资源释放 线程终止

    千次阅读 2011-12-02 16:15:44
    线程创建时,系统会分配给线程一些资源,我们可以看到的就是线程描述符,线程堆栈,在系统内部还会有更复杂的系统维护一些信息,在线程创建时,内核总会为其维护一些资源,比较理想的情况是线程运行结束后,释放系统...
  • 如何等待一个线程结束。那么如果不希望等待线程结束,而是根据问题的需要随时都要中断线程使其结束,这种对线程的控制方法该如何实现呢?  解决思路  首先必须先明确“中断”这个概念的实际含义,这里的中断是指...
  • C#如何优雅的终止一个线程

    万次阅读 2017-10-11 13:28:56
    大家都知道在C#里面,我们可以使用Thread.Start方法来启动一个线程,当我们想停止执行的线程时可以使用Thread.Abort方法来强制停止正在执行的线程,但是请注意,你确定调用了Thread.Abort方法后线程就立刻停止了吗?...
  • 如何停止java的线程一直是一个开发...也有好多人问过我,所以今天在这里总结一下希望可以让更多的人知道在java中如何安全的结束一个正在运行的线程。 在Java的多线程编程中,java.lang.Thread类型包含了一些列的方
  • 我在Android UI线程执行一些程序,有一个很耗时的程序,所以我把它放在另一个线程中。 1.在这个子线程运行后,UI线程会开始执行某个程序 2.这个程序将会在子线程中创建一些数据 这是我的解决方案: Car car...
  • 之前对于线程和方法的理解有些偏差,竟稀里糊涂的认为一个线程就是一个方法,一个方法就是一个线程。尤其在理解ThreadLocal执行原理的时候,更是晕乎 (ThreadLocal把当前线程作为key,来维护管理一个可变的对象,...
  • QT (启动一个线程)

    万次阅读 2018-12-01 17:06:47
    启动一个线程的步骤: (1) 创建一个自己的线程类继承QT中的QThread类 创建线程类WorkThread; (2) 在自己的WorkThreak类中重新实现run()函数, 该函数是一个死循环, 主要是完成自己需要的功能代码 (3) 使用自己的类...
  • JAVA里面如何让一个线程死亡或结束

    万次阅读 热门讨论 2008-10-30 05:32:00
    原文:http://www.java2000.net/p11369这问题也是很常见的问题,.../** * JAVA里面如何使用一个线程死亡或结束. * @author 赵学庆,Java世纪网(java2000.net) * */public class T { public static void
  • 易语言大漠多线程模板多线程结束

    千次阅读 2020-06-02 09:06:06
    为了在线程结束时保证线程安全,首先采用WaitForSingleObject自然等待结束,设置了30s的等待时间,当自然结束失败时,如果等待自然线程失败,没有办法的情况下,只能强制粗暴的结束线程,同时我们对象对计数器进行...
  • 多个线程调用同一个线程函数

    千次阅读 2012-03-08 20:15:53
    多个线程调用同一个线程函数 悬赏分:50 - 解决时间:2007-12-11 13:59 如题,能这样吗?因为有很多个操作,但是这些操作都是一样的,所以想用相同的线程函数,但是感觉运行时线程还是一个一个运行,并没有...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 716,317
精华内容 286,526
关键字:

如何结束一个线程