Android - 停止线程的最佳和安全的方法

时间:2011-12-14 14:00:10

标签: android thread-safety

我想知道在Android中阻止线程的最佳方法是哪种。我知道我可以使用AsyncTask代替它,并且有一个cancel()方法。我必须在我的情况下使用Thread。以下是我使用Thread

的方法
Runnable runnable = new Runnable() {
        @Override
        public void run() {
            //doing some work
        }
    };
new Thread(runnable).start();

那么,有没有人知道哪个是阻止线程的最佳方式?

14 个答案:

答案 0 :(得分:80)

你应该让你的线程支持中断。基本上,您可以致电yourThread.interrupt()停止线程,在您的run()方法中,您需要定期检查Thread.interrupted()的状态

有一个很好的教程here

答案 1 :(得分:27)

这种情况与标准Java没有任何不同。您可以使用标准方法来停止线程:

class WorkerThread extends Thread {
    volatile boolean running = true;

    public void run() {
        // Do work...
        if (!running) return;
        //Continue doing the work
    }
}

主要思想是不时检查字段的值。当您需要停止线程时,将running设置为false。此外,正如克里斯指出的那样,你可以使用中断机制。

顺便说一句,当您使用AsyncTask时,您的apporach不会有太大差异。唯一的区别是您必须从您的任务中调用isCancel()方法,而不是使用特殊字段。如果你调用cancel(true),但没有实现这种机制,那么线程仍然不会自动停止,它将运行到最后。

答案 2 :(得分:18)

在Android上,适用的规则与普通Java环境相同。 在Java中,线程没有被杀死,但线程的停止是以合作方式完成的。要求线程终止,然后线程可以正常关闭。

通常使用volatile boolean字段,当线程设置为相应的值时,线程会定期检查并终止。

不会使用boolean检查线程是否应终止。如果你使用volatile作为字段修饰符,这将是可靠的,但如果你的代码变得更复杂,而是使用while循环内的其他阻塞方法,可能会发生,你的代码会<强烈>不终止或者至少需要更长时间

  

某些阻止库方法支持中断。

每个线程都有一个布尔标志中断状态,你应该使用它。它可以像这样实现:

public void run() {

   try {
      while(!Thread.currentThread().isInterrupted()) {
         // ...
      }
   } catch (InterruptedException consumed)
      /* Allow thread to exit */
   }

}

public void cancel() { interrupt(); }

源自Java Concurrency in Practice的源代码。由于cancel()方法是公共的,您可以让另一个线程根据需要调用此方法。

还有一个命名不佳的静态方法interrupted,它清除了当前线程的中断状态。

答案 3 :(得分:15)

可以用来停止线程的Thread.stop()方法已被弃用;了解更多信息; Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?

你最好的选择是拥有一个线程本身参考的变量,并在变量等于某个值时自愿退出。然后,当您希望线程退出时,可以操作代码中的变量。当然,您也可以使用AsyncTask代替。

答案 4 :(得分:2)

目前,不幸的是我们无法阻止线程......

在Matt的答案中添加一些内容我们可以调用interrupt()但是这不会停止线程...只是告诉系统在系统想要杀死一些线程时停止线程。休息由系统完成,我们可以通过调用interrupted()来检查它。

[P.S。 :如果你真的和interrupt()一起去,我会要求你在打电话给interrupt()后的短暂睡眠时做一些实验。

答案 5 :(得分:2)

问题是你需要检查线程是否正在运行!?

字段:

private boolean runningThread = false;

在帖子中:

new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep((long) Math.floor(speed));
                        if (!runningThread) {
                            return;
                        }
                        yourWork();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

如果你想停止线程,你应该在下面的字段

private boolean runningThread = false;

答案 6 :(得分:1)

以下两种方式首选停止线程。

  1. 创建一个volatile布尔变量并将其值更改为false并检查线程内部。

    volatile isRunning = false;

    public void run(){   if(!isRunning){return;} }

  2. 或者您可以使用可以在线程内接收的interrupt()方法。

    SomeThread.interrupt();

    public void run(){   if(Thread.currentThread.isInterrupted()){return;} }

答案 7 :(得分:0)

我用过这种方法。

Looper.myLooper().quit();

你可以尝试。

答案 8 :(得分:0)

这对我有用。在主要活动中引入一个静态变量,并定期检查它是如何做到的。

public class MainActivity extends AppCompatActivity {


//This is the static variable introduced in main activity
public static boolean stopThread =false;



  protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Thread thread = new Thread(new Thread1());
    thread.start();

    Button stp_thread= findViewById(R.id.button_stop);

    stp_thread.setOnClickListener(new Button.OnClickListener(){
           @Override
           public void onClick(View v){
              stopThread = true;
           }

     }

  }


  class Thread1 implements Runnable{

        public void run() {

        // YOU CAN DO IT ON BELOW WAY 
        while(!MainActivity.stopThread) {
             Do Something here
        }


        //OR YOU CAN CALL RETURN AFTER EVERY LINE LIKE BELOW

        process 1 goes here;

        //Below method also could be used
        if(stopThread==true){
            return ;
        }
        // use this after every line



        process 2 goes here;


        //Below method also could be used
        if(stopThread==true){
            return ;
        }
        // use this after every line


        process 3 goes here;


        //Below method also could be used
        if(stopThread==true){
            return ;
        }
        // use this after every line


        process 4 goes here;



       }
   }

}

答案 9 :(得分:0)

如果您的项目中有带有处理程序的线程类,那么从片段类之一开始时,如果您想在此处停止,那么该解决方案是如何停止并避免在片段从堆栈中删除时导致应用程序崩溃。 >

此代码位于科特林中。完美。

class NewsFragment : Fragment() {

    private var mGetRSSFeedsThread: GetRSSFeedsThread? = null

    private val mHandler = object : Handler() {

        override fun handleMessage(msg: Message?) {


            if (msg?.what == GetRSSFeedsThread.GETRSSFEEDSTHREAD_SUCCESS) {
                val updateXMLdata = msg.obj as String
                if (!updateXMLdata.isNullOrEmpty())
                    parseUpdatePager(CommonUtils.getJSONObjectFromXML(updateXMLdata).toString())

            } else if (msg?.what == GetRSSFeedsThread.GETRSSFEEDSTHREAD_SUCCESS) {
                BaseActivity.make_toast(activity, resources.getString(R.string.pleaseTryAgain))
            }

        }
    }
    private var rootview: View? = null;
    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        rootview = inflater?.inflate(R.layout.fragment_news, container, false);

        news_listView = rootview?.findViewById(R.id.news_listView)
        mGetRSSFeedsThread = GetRSSFeedsThread(this.activity, mHandler)


        if (CommonUtils.isInternetAvailable(activity)) {
            mGetRSSFeedsThread?.start()
        }


        return rootview
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true);

    }



    override fun onAttach(context: Context?) {
        super.onAttach(context)
        println("onAttach")
    }

    override fun onPause() {
        super.onPause()
        println("onPause fragment may return to active state again")

        Thread.interrupted()

    }

    override fun onStart() {
        super.onStart()
        println("onStart")

    }

    override fun onResume() {
        super.onResume()
        println("onResume fragment may return to active state again")

    }

    override fun onDetach() {
        super.onDetach()
        println("onDetach fragment never return to active state again")

    }

    override fun onDestroy() {
        super.onDestroy()

        println("onDestroy fragment never return to active state again")
       //check the state of the task
        if (mGetRSSFeedsThread != null && mGetRSSFeedsThread?.isAlive!!) {
            mGetRSSFeedsThread?.interrupt();
        } else {

        }

    }

    override fun onDestroyView() {
        super.onDestroyView()
        println("onDestroyView fragment may return to active state again")



    }

    override fun onStop() {
        super.onStop()
        println("onStop fragment may return to active state again")



    }
}

当您从当前片段切换到任何其他片段或活动时,以上代码将停止正在运行的线程。当您返回当前片段时也会重新创建

答案 10 :(得分:0)

尝试这样

Thread thread = new Thread() {
    @Override
    public void run() {
        Looper.prepare();   
        while(true){ 
            Log.d("Current Thread", "Running"); 
            try{
               Thread.sleep(1000);
            }catch(Exeption Ex){ }
        }
    }
}

thread.start();
thread.interrupt();

答案 11 :(得分:0)

我的要求与问题略有不同,但这仍然是停止线程执行其任务的一种有用方法。我想要做的就是在退出屏幕时停止线程,并在返回屏幕时继续执行。

根据Android文档,这将是建议的 stop 方法的替代方法,该方法已从API 15中弃用

  

停止的许多用法应替换为简单修改某些代码的代码   指示目标线程应停止运行的变量。的   目标线程应定期检查此变量,然后从   如果变量表明它的运行方法有序   是要停止运行。

我的线程类

   class ThreadClass implements Runnable {
            ...
                  @Override
                        public void run() {
                            while (count < name.length()) {

                                if (!exited) // checks boolean  
                                  {
                                   // perform your task
                                                     }
            ...

OnStop和OnResume看起来像这样

  @Override
    protected void onStop() {
        super.onStop();
        exited = true;
    }

    @Override
    protected void onResume() {
        super.onResume();
        exited = false;
    }

答案 12 :(得分:0)

我们知道Thread.stop()在JAVA中已被弃用,Thread.stop在后台调用了线程上的interrupt()方法来停止它,因此Interrupt会从保持该状态的方法中抛出。线程在执行完成后等待其他线程通知。如果在执行线程时未处理中断,则不会对线程造成任何影响,例如if(Thread.interrupted())return; 因此,总的来说,我们基本上需要管理线程的开始和停止,就像调用start()之类的Thread.start()方法一样,在线程的while(true)方法内部启动run()并在每次迭代中检查中断状态并从线程返回。

请注意,在以下情况下线程不会死亡:

  1. 线程尚未从run()返回。
  2. 该线程拥有的任何对象都是可访问的。 (这暗示着要为GC做其余的工作而将其引用作空/处置)

答案 13 :(得分:-1)

在任何Activity类的内部,您创建一个方法,该方法将为线程实例分配NULL,该方法可用作停止线程执行的折旧stop()方法的替代方法:

public class MyActivity extends Activity {

private Thread mThread;  

@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);


        mThread =  new Thread(){
        @Override
        public void run(){
            // Perform thread commands...
    for (int i=0; i < 5000; i++)
    {
      // do something...
    }

    // Call the stopThread() method.
            stopThread(this);
          }
        };

    // Start the thread.
        mThread.start(); 
}

private synchronized void stopThread(Thread theThread)
{
    if (theThread != null)
    {
        theThread = null;
    }
}
}

这对我没有问题。