怎样停止让线程停止执行的方法解决方法

终止线程 有两种情况可以使线程结束:控制函数结束或者根本就不允许线程完成,而提前终止它。我们可以想象在WORD中进行后台打印,如果打印结束了,那线程就可以结束了。如果用户中止了打印,那后台打印线程也要终止了。本文将主要介绍对这两种情况的实现,并且介绍如何获得线程的结束代码。 对于工作线程,结束它是比较容易的:退出线程函数然后返回一个结束原因的代码就是了。用户可以使用AfxEndThread函数或直接利用return返回。通常0代表成功返回,这不是硬性规定,一切要取决于你了。对于用户界面线程,调用::PostQuitMessage,它所要的唯一的参数就是返回代码,也就是工作线程中的那个码,性质是一样的。0通常代表成功。 提前终止一个线程也不难:在线程函数中调用AfxEndThread就是了,其中要传入的参数就是返回代码。这会停止线程的执行,释放线程栈,及与线程相关的DLL,并从内存中删除线程对象。AfxEndThread必须在线程函数内调用,如果用户希望从一个线程结束另一个线程,则需要在两个线程间建立通信机制。 如果需要获得线程返回代码,只需要调用::GetExitCodeThread就可以了。这个函数的具体作用就看大家具体去查帮助了。它传入的是线程的句柄,和一个提向返回代码的指针。将来就从那个指针得到返回代码。如果线程仍然处于活动状态,那么::GetExitCodeThread得到的返回代码为STILL_ACTIVE,如果已经退出则得到的是返回代码的地址。获得CWinThread对象的返回代码还需要一点麻烦,通常,当CWinThread线程结束时,线程对象就删除了,因为这个对象不存在了,也就没有办法访问对象的m_hThread变量了,为了避免这种情况,可以有两种方法: 将m_bAutoDelete设置为FALSE,这使得线程结束后CWinThread对象仍然存在,这样用户就可以访问m_hThread了,但是如果用户使用这种方法,用户需要自己析构CWinThread对象。这种方法是推荐的方法。 下一个方法是另外保存线程的句柄。在线程创建后,将m_hThread保存在另一个变量中,以后访问这个变量就是了。但是要小心,在复制句柄以前线程并没有结束,最安全的方法是在AfxBeginThread中传入CREATE_SUSPENDED,保存句柄,然后通过调用ResumeThread,重新开始线程。这两种方法都可以帮助用户得到CWinThread对象的返回代码。
对于Worker线程,终止线程可以使用线程的退出码作为返回值从线程函数返回。  对于UI线程,因为有消息循环,需要发送一个WM_QUIT消息到线程的消息队列,当线程接收到WM_QUIT消息时退出消息循环。因此,结束线程可以在线程内部调用SDK的PostQuitMessage函数,发送WM_QUIT消息。  PostQuitMessage函数的定义如下:  void PostQuitMessage(int nExitCode);  其中:  nExitCode:线程的退出码。  MFC还提供了AfxEndThread函数,Worker线程和UI线程都可以通过在线程内部调用AfxEndThread函数结束线程。  AfxEndThread函数的定义如下:  void AfxEndThread(UINT nExitCode, BOOL bDelete = TRUE);  其中:  nExitCode:线程的退出码。  在MFC的THRDCORE.CPP中,AfxEndThread函数的相关代码如下:  // THRDCORE.CPP  void AFXAPI AfxEndThread(UINT nExitCode, BOOL bDelete)  {  // remove current CWinThread object from memory  AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();  CWinThread* pThread = pState-&m_pCurrentWinT  if (pThread != NULL)  {  ASSERT_VALID(pThread);  ASSERT(pThread != AfxGetApp());  // cleanup OLE if required  if (pThread-&m_lpfnOleTermOrFreeLib != NULL)  (*pThread-&m_lpfnOleTermOrFreeLib)(TRUE, FALSE);  if (bDelete)  pThread-&Delete();  pState-&m_pCurrentWinThread = NULL;  }  // allow cleanup of any thread local objects  AfxTermThread();  // allow C-runtime to cleanup, and exit the thread  _endthreadex(nExitCode);  }  从MFC代码中可以看出,AfxEndThread函数通过调用_endthreadex函数终止线程。此外,函数还进行释放线程的堆栈、删除线程对象等工作。  如果在其它线程中终止该线程,必须采用线程通信的方法实现。其中一种简单的方法是建立一个变量,让线程监视该变量,当该变量为某个值时,则终止线程。  (1)创建1个基于对话框的应用程序,名称为Demo。  (2)在IDD_DEMO_DIALOG对话框资源中添加控件,如表所示。  类型  ID  标题  Static  IDC_STATIC  数据:  Edit  IDC_DATA    Button  IDC_BEGIN_THREAD  启动线程  Button  IDC_END_THREAD  终止线程
(3)在文件中定义线程传递参数的数据结构,代码如下:   // DemoDlg.h  typedef struct THREAD_PARAM  {  HWND hW  int nD  BOOL bE  }_THREAD_PARAM;  (4)在CDemoDlg类中添加成员变量,代码如下:  // DemoDlg.h  protected:  CWinThread* m_pT  THREAD_PARAM m_ThreadP  (5)在CDemoDlg类的构造函数中初始化成员变量,代码如下:  // DemoDlg.cpp  CDemoDlg::CDemoDlg(CWnd* pParent /*=NULL*/)  : CDialog(CDemoDlg::IDD, pParent)  {  // ...  m_pThread = NULL;  m_ThreadParam.nData = 0;  }  (6)在CDemoDlg类的OnInitDialog函数中添加如下代码:  // DemoDlg.cpp     BOOL CDemoDlg::OnInitDialog()  {  CDialog::OnInitDialog();  // &  SetDlgItemInt(IDC_DATA, m_nData);  return TRUE;  }  (7)在文件中定义线程消息,代码如下:  // DemoDlg.h  #define WM_THREADMSG WM_USER+1  (8)在文件中定义线程函数,代码如下:  // DemoDlg.h  UINT ThreadProc(LPVOID pParam);  // DemoDlg.cpp  UINT ThreadProc(LPVOID pParam)  {  //线程参数  THREAD_PARAM* pThreadParam = (THREAD_PARAM*)pP  while (!pThreadParam-&bExit)  {  Sleep(100);  pThreadParam-&nData++;  //向主线程窗口发送消息  ::PostMessage(pThreadParam-&hWnd, WM_THREADMSG, 0, 0);  }  return 0;  }  (9)在CDemoDlg类中分别为Button控件添加BN_CLICKED添加消息处理函数,代码如下:  // DemoDlg.cpp  void CDemoDlg::OnBeginThread()  {  if (m_pThread != NULL)  {  AfxMessageBox(_T("线程已经启动。"));    }  m_ThreadParam.hWnd = m_hW  m_ThreadParam.bExit = FALSE;  //启动线程,初始为挂起状态  m_pThread = AfxBeginThread(ThreadProc, &m_ThreadParam,  THREAD_PRIORITY_ABOVE_NORMAL, 0, CREATE_SUSPENDED);  //线程结束时不自动删除  m_pThread-&m_bAutoDelete = FALSE;  //恢复线程运行  m_pThread-&ResumeThread();  }  void CDemoDlg::OnEndThread()  {  if (m_pThread == NULL)  {  AfxMessageBox(_T("线程已经终止。"));    }  m_ThreadParam.bExit = TRUE;  //等待线程结束  ::WaitForSingleObject(m_pThread-&m_hThread, INFINITE);  delete m_pT  m_pThread = NULL;  }  (10)在CDemoDlg类中添加自定义消息处理函数,代码如下:  // DemoDlg.h  afx_msg LRESULT OnMsgFunc();  // DemoDlg.cpp  BEGIN_MESSAGE_MAP(CDemoDlg, CDialog)  ON_MESSAGE(WM_THREADMSG, OnMsgFunc)  END_MESSAGE_MAP()  LRESULT CDemoDlg::OnMsgFunc()  {  SetDlgItemInt(IDC_DATA, m_ThreadParam.nData);  return 1;     }
阅读(...) 评论() &这段代码用destroy终止线程,也能用,貌似还是有问题的:
private void viewOnline() {if (currentNewsletter == null) {Log.e(Constants.APP_NAME, "No newsletter selected");}final ProgressDialog d = new ProgressDialog(this);d.setMessage("Downloading...");d.show();final Context context = getApplicationContext();t = new Thread(new Runnable() {public void run() {String fileName = currentNewsletter.mFLog.d(Constants.APP_NAME, "Downloading/showing: " + fileName);final File file = Utilities.getFileFromURL(context, currentNewsletter.mUrl, currentNewsletter.mExpectedSizeInBytes, fileName, false);d.dismiss();// Now we can show the fileviewPDF(file);}});t.start();Context.MODE_WORLD_WRITEABLE).getAbsolutePath());}private void viewPDF(File file) {Intent intent = new Intent(Intent.ACTION_VIEW);intent.setDataAndType(Uri.fromFile(file), "application/pdf");try {startActivity(intent);} catch (Exception e) {Toast.makeText(this, "No Application Available to View PDF", Toast.LENGTH_SHORT).show();}}@Overrideprotected void onStop() {finish();super.onStop();}@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_BACK) {t.destroy();Intent i = new Intent(NewslettersActivity.this,MainMenuActivity.class);startActivity(i);finish();}return super.onKeyDown(keyCode, event);}
虽然程序没崩溃,但是会有很多异常的log,说明这方法有点问题,有没有更温柔的方法让一个线程终止并等待其结束?
11-09 11:42:28.740: E/AndroidRuntime(1538): FATAL EXCEPTION: main11-09 11:42:28.740: E/AndroidRuntime(1538): java.lang.NoSuchMethodError: Thread.destroy()11-09 11:42:28.740: E/AndroidRuntime(1538):
at java.lang.Thread.destroy(Thread.java:600)11-09 11:42:28.740: E/AndroidRuntime(1538):
at com.rathbones.src.NewslettersActivity.onKeyDown(NewslettersActivity.java:144)11-09 11:42:28.740: E/AndroidRuntime(1538):
at android.view.KeyEvent.dispatch(KeyEvent.java:1037)11-09 11:42:28.740: E/AndroidRuntime(1538):
at android.app.Activity.dispatchKeyEvent(Activity.java:2068)11-09 11:42:28.740: E/AndroidRuntime(1538):
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1643)11-09 11:42:28.740: E/AndroidRuntime(1538):
at android.view.ViewRoot.deliverKeyEventToViewHierarchy(ViewRoot.java:2471)11-09 11:42:28.740: E/AndroidRuntime(1538):
at android.view.ViewRoot.handleFinishedEvent(ViewRoot.java:2441)11-09 11:42:28.740: E/AndroidRuntime(1538):
at android.view.ViewRoot.handleMessage(ViewRoot.java:1735)11-09 11:42:28.740: E/AndroidRuntime(1538):
at android.os.Handler.dispatchMessage(Handler.java:99)11-09 11:42:28.740: E/AndroidRuntime(1538):
at android.os.Looper.loop(Looper.java:123)11-09 11:42:28.740: E/AndroidRuntime(1538):
at android.app.ActivityThread.main(ActivityThread.java:4627)11-09 11:42:28.740: E/AndroidRuntime(1538):
at java.lang.reflect.Method.invokeNative(Native Method)11-09 11:42:28.740: E/AndroidRuntime(1538):
at java.lang.reflect.Method.invoke(Method.java:521)11-09 11:42:28.740: E/AndroidRuntime(1538):
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)11-09 11:42:28.740: E/AndroidRuntime(1538):
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)11-09 11:42:28.740: E/AndroidRuntime(1538):
at dalvik.system.NativeStart.main(Native Method)11-09 11:42:28.760: W/ActivityManager(59):
Force finishing activity com.rathbones.src/.NewslettersActivity
该问题被发起重新开启投票
投票剩余时间:
之前被关闭原因:
该问题被发起删除投票
投票剩余时间:
距离悬赏到期还有:
参与关闭投票者:
关闭原因:
该问题已经被锁定
锁定原因:()
保护原因:避免来自新用户不合宜或无意义的致谢、跟帖答案。
该问题已成功删除,仅对您可见,其他人不能够查看。
Java线程的常见的几种状态1.new(新建)。2.runnable(就绪)。3.Running(正在运行)。4.Block(阻塞)。5.sleep(睡眠)6.Dead(死亡)。当run()方法或main()方法结束后,线程就进入终止状态,也就是结束啦。你想办法让run()执行到最后就可以了, 发出中断信息是API中所推荐的 Thread.interrupt(),简单的还可以设置一个BOOLEAN 值去控制, 一般你需要控制结束大多都是线程里面会是一个循环机制,每一次循环检测这个BOOLEAN 值变量即可。按照上述,就是finish() 之后改变BOOLEAN 之后就行了。
的方式下补充下,这种方式一般还需要等待线程的结束。
boolean flag =Thread secondary = new Thread(new Runnable() {@Overridepublic void run() {while (flag) {// do something}}});secondary.start(); //start the threadflag = // this will force secondary to finish its executiontry {secondary.join(); // wait for secondary to finish} catch (InterruptedException e) {throw new RuntimeException(e);}
不要依赖 interrupt 方法,线程能够被 interrupt 前提是线程处于可以被中断的状态,比如:sleep,wait 等等,如果线程处于其他状态,interrupt 是没有用的
当然上面提到的很多设置 boolean 变量的方法,是可取的,但是需要注意的是,往往设置 boolean 变量是在其他线程里面进行设置,建议使用 volatile boolean
还有一种方法就是,throw exception 方式,比如:代码正在跟流打交道,或给网络打交道,或者读取数据库,此时可以通过关闭流,关闭网络,或者关闭数据库,这样会很快的抛出异常,通过对异常的捕获,来完成线程的工作
线程一般用Thread.interrupt()来终止线程run方法中使用while(!Thread.interrupted()){ 具体代码}关于具体代码部分,如果是阻塞代码,有些是可终止,有些是不可终止在可终止的时候,处理interruptedException
阻塞不可停止的时候,就要适当的加上标志
具体阅读Think in Java 并发那一章
下载地址:/file/bhu6ih4t
interrupt 方法有些&除暴&,我一般使用设置标志位的方法!
首先,不是有问题,是有很大的问题。。。你确定你的程序没有挂掉?log里可见:11-09 11:42:28.740: E/AndroidRuntime(1538): FATAL EXCEPTION: main11-09 11:42:28.740: E/AndroidRuntime(1538): java.lang.NoSuchMethodError: Thread.destroy()
注意这个NoSuchMethodError,另外见Java API:/javase/7/docs/api/java/lang/Thread.html#destroy%28%29Thread.destroy()方法根本从来就没有实现过!
你在 main 线程里 调用thread1.destroy(), thread1安然无恙,你的main线程会拿到一个NoSuchMethodError(注意是Error!),除非你在main里特别去catch了这个error(一般不会有人这么干吧),main线程会直接挂掉。
用Thread.stop()也是不靠谱的,有多线程问题。
解决方法就是大家说的,1)使用volatile的标志位;2)用线程打扰机制,程序中 while(!thread.interrupted())检查;在sleep,wait的地方catch interruptedException。
《Java Concurrency in Practice》推荐线程打扰机制,见:Interruption is usually the most sensible way to implement cancellation
另外注意,Thread里:
public static boolean interrupted()
public boolean isInterrupted()是不一样的,前面的会清除打扰标志位,具体使用的时候要 考虑一下。
不是您所需,查看更多相关问题与答案
德问是一个专业的编程问答社区,请
后再提交答案
关注该问题的人
共被浏览 (30394) 次安全检查中...
请打开浏览器的javascript,然后刷新浏览器
diannao.wang 浏览器安全检查中...
还剩 5 秒&Java多线程之中断机制(如何处理中断?)_Linux编程_Linux公社-Linux系统门户网站
你好,游客
Java多线程之中断机制(如何处理中断?)
来源:Linux社区&
作者:hapjin
这篇文章主要记录使用 interrupt() 方法中断线程,以及如何对InterruptedException进行处理。感觉对InterruptedException异常进行处理是一件谨慎且有技巧的活儿。
由于使用stop()方法停止线程非常的暴力,人家线程运行的好好的,突然就把人家杀死了,线程占用的锁被强制释放,极易导致数据的不一致性。可参考对stop()方法的介绍。
因此,提出了一种温和的方式:请求另外一个线程不要再执行了,这就是中断方式。
二,中断及如何响应中断?
如何优雅地响应中断真的是太高深了,看到这篇文章:就吓了一跳。下面只是记录一些最简单的我对响应中断的理解。
假设某个线程要不停地处理某件事情(比如 i 一直自增),但是还有个要求:在处理事情前,先要检查下这个线程是否被中断,如果已经被中断,处理就应该结束。
下面是一些例子,这些例子摘自《JAVA多线程核心编程技术》
1 public class Run {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(2000);
thread.interrupt();//请求中断MyThread线程
} catch (InterruptedException e) {
System.out.println("main catch");
e.printStackTrace();
System.out.println("end!");
main线程睡眠2000ms后,执行第8行中断MyThread线程。
1 public class MyThread extends Thread {
public void run() {
super.run();
for (int i = 0; i & 500000; i++) {
if (this.interrupted()) {
System.out.println("should be stopped and exit");
System.out.println("i=" + (i + 1));
System.out.println("this line is also executed. thread does not stopped");//尽管线程被中断,但并没有结束运行。这行代码还是会被执行
当MyThread获得CPU执行时,第6行的 if 测试中,检测到中断标识被设置。即MyThread线程检测到了main线程想要中断它的 请求。
大多数情况下,MyThread检测到了中断请求,对该中断的响应是:退出执行(或者说是结束执行)。
但是,上面第5至8行for循环,是执行break语句跳出for循环。但是,线程并没有结束,它只是跳出了for循环而已,它还会继续执行第12行的代码....
因此,我们的问题是,当收到了中断请求后,如何结束该线程呢?
一种可行的方法是使用 return 语句 而不是 break语句。。。。。哈哈。。。
当然,一种更优雅的方式则是:抛出InterruptedException异常。
看下面MyThread类的代码:
1 public class MyThread extends Thread {
public void run() {
super.run();
for (int i = 0; i & 500000; i++) {
if (this.interrupted()) {
System.out.println("should be stopped and exit");
throw new InterruptedException();
System.out.println("i=" + (i + 1));
System.out.println("this line cannot be executed. cause thread throws exception");//这行语句不会被执行!!!
}catch(InterruptedException e){
System.out.println("catch interrupted exception");
e.printStackTrace();
当MyThread线程检测到中断标识为true后,在第9行抛出InterruptedException异常。这样,该线程就不能再执行其他的正常语句了(如,第13行语句不会执行)。
因此,上面就是一个采用抛出异常的方式来结束线程的示例。尽管该示例的实用性不大。原因在 IBM的中:我们 生吞了中断。
在第14行,我们直接catch了异常,然后打印输出了一下而已,调用栈中的更高层的代码是无法获得关于该异常的信息的。
第16行的e.printStackTrace()作用就相当于
&(仅仅记录 InterruptedException 也不是明智的做法,因为等到人来读取日志的时候,再来对它作出处理就为时已晚了。)&---摘自参考博文
上面我们是在run()方法中抛出异常,符合这里描述的:
有时候抛出 InterruptedException 并不合适,例如当由 Runnable 定义的任务调用一个
可中断的方法时,就是如此。在这种情况下,不能重新抛出 InterruptedException,但是
您也不想什么都不做。当一个阻塞方法检测到中断并抛出 InterruptedException 时,它
清除中断状态。如果捕捉到 InterruptedException 但是不能重新抛出它,那么应该保留
中断发生的证据,以便调用栈中更高层的代码能知道中断,并对中断作出响应。该任务可以
通过调用 interrupt() 以 &重新中断& 当前线程来完成,如清单 3 所示。 -----&摘自参考博文&
因为,run方法是实现的Runnable接口中的方法。不能像下面这样定义,也即上面所说的:&不能重新抛出InterruptedException&。
public void run() throws InterruptedException{//这是错误的
//do something...
因此,一个更好的解决方案是:调用 interrupt() 以 &重新中断& 当前线程。改进MyThread类中catch异常的方式,如下:
1 public class MyThread extends Thread {
public void run() {
super.run();
for (int i = 0; i & 500000; i++) {
if (this.interrupted()) {
System.out.println("should be stopped and exit");
throw new InterruptedException();
System.out.println("i=" + (i + 1));
System.out.println("this line cannot be executed. cause thread throws exception");
}catch(InterruptedException e){
/**这样处理不好
* System.out.println("catch interrupted exception");
* e.printStackTrace();
Thread.currentThread().interrupt();//这样处理比较好
这样,就由 生吞异常 变成了 将 异常事件 进一步扩散了。
参考博文:Java 理论与实践: 处理 InterruptedException&
本文永久更新链接地址:
相关资讯 & & &
& (12/22/:34)
& (11/07/:39)
& (01月02日)
& (11/29/:56)
& (09/01/:22)
   同意评论声明
   发表
尊重网上道德,遵守中华人民共和国的各项有关法律法规
承担一切因您的行为而直接或间接导致的民事或刑事法律责任
本站管理人员有权保留或删除其管辖留言中的任意内容
本站有权在网站内转载或引用您的评论
参与本评论即表明您已经阅读并接受上述条款}

我要回帖

更多关于 ipad停止使用解决方法 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信