【问题标题】:Android - Return boolean value from within a ThreadAndroid - 从线程内返回布尔值
【发布时间】:2015-05-30 05:35:39
【问题描述】:

我试图从Thread 中的runnable 方法返回boolean 值。我需要知道HTTPRequest 方法是否成功。问题是我知道请求是成功的,但我总是得到false 作为响应。


public boolean SmsDelivery;

SmsDelivery=sendSMS(prefix, number);

 if(SmsDelivery){
    //Do stuff
}
//The method itself
    private boolean sendSMSinThread(final String str){
        final AtomicBoolean b = new AtomicBoolean(false);
        Thread thread = new Thread(new Runnable(){

            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost(str);
            @Override
            public void run() {
                try {
                    // Execute HTTP Post Request
                    //HttpResponse response = httpclient.execute(httppost);
                    httpclient.execute(httppost);
                    b.set(true);
                } catch (ClientProtocolException e) {
                    // TODO Auto-generated catch block
                    Log.e("Thread:","Unable to generate call"+e);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    Log.e("Thread:","Unable to generate call"+e);
                }
            }
        });
        thread.start();
        return b.get();
    }


更新

根据这里的建议,我设法得到了想要的结果,但是,我不知道哪种方法更适合我的需要。有人可以推荐我的最佳用法吗?使用AsyncTaskThread + join 方法。
第一种方法是通过以下方式使用 AsyncTask:

SmsTask smsTask = new SmsTask();
        try{
            smsResult = smsTask.execute(urlString).get();
        }catch (InterruptedException e){
            e.printStackTrace();
        }catch (ExecutionException e){
            e.printStackTrace();
        }

//the class itself
     class SmsTask extends AsyncTask<String,Void, Boolean> {
         final AtomicBoolean b = new AtomicBoolean(false);

        @Override
        protected Boolean doInBackground(String... params) {
            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost(params[0]);

            try {
                httpclient.execute(httppost);
                b.set(true);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return b.get();
        }

        @Override
        protected void onPostExecute(Boolean result) {
            // result holds what you return from doInBackground
            Log.i("result from async: ",""+result);
            super.onPostExecute(result);
        }
    }


第二种方法,几乎​​和我最初发布的一样,但使用了“thread.join()”方法:

thread.start();
try {
    thread.join();
} catch (InterruptedException e) {
    e.printStackTrace();
}
return b.get();

【问题讨论】:

  • 这段代码中是否有任何东西等待线程真正完成?您似乎启动了线程,然后在线程有时间做任何事情之前立即检查它的值。
  • 看看我的回答here。该操作询问了 AsyncTask,但同样的概念可以应用于您的案例
  • 你不应该返回布尔值。相反,您等待线程完成,然后通过b.get() 询问或查看我的答案

标签: java android multithreading atomicboolean


【解决方案1】:

试试这个

thread.start();
thread.join();
return b.get();

【讨论】:

【解决方案2】:

您应该等到任务执行完毕。在这种情况下,您应该在单线程中运行此代码(新线程无用)或使用 Android 的 AsyncTask-like 类并在 onPostExecute 方法中处理结果。

【讨论】:

    【解决方案3】:

    你可以使用一些观察者模式之类的。

    类似这样的:

    //有一个自定义的Runnable

    public class HTTPRequestRunnable implements Runnable {
    
        HttpClient httpclient;
        HttpPost httppost;
        private HTTPRequestListner listner;
    
        public HTTPRequestRunnable(String str, HTTPRequestListner listner) {
            httpclient = new DefaultHttpClient();
            httppost = new HttpPost(str);
            this.listner = listner;
    
        }
        @Override
        public void run() {
            try {
                // Execute HTTP Post Request
                //HttpResponse response = httpclient.execute(httppost);
                httpclient.execute(httppost);
                if (listner != null)
                    listner.onSuccess();
            } catch (ClientProtocolException e) {
                if (listner != null)
                    listner.onFail();
                Log.e("Thread:", "Unable to generate call" + e);
            } catch (IOException e) {
                if (listner != null)
                    listner.onFail();
                e.printStackTrace();
                Log.e("Thread:", "Unable to generate call" + e);
            }
        }
    
    
        public void setListner(HTTPRequestListner listner) {
            this.listner = listner;
        }
        /**
         * here is your observer class
         */
    
        public interface HTTPRequestListner {
    
            void onSuccess();
    
            void onFail();
        }
    }
    

    然后在你的方法中像这样使用它:

    public void sendSMSinThread(final String str){
    
            HTTPRequestRunnable httpRequestRunnable = new HTTPRequestRunnable(str,new HTTPRequestListner() {
                @Override
                public void onSuccess() {
                    //DO your logic here on success
                }
    
                @Override
                public void onFail() {
                   //DO your logic here on fail
                }
            });
    
            Thread thread = new Thread(httpRequestRunnable);
            thread.start();
        }
    

    给你,希望对你有帮助

    【讨论】:

      【解决方案4】:

      有多种方法可以实现这一点。

      1. 使用可调用的,而不是可运行的,因为可调用的调用方法可以返回结果
      2. 坚持你的方法,但在返回结果之前,调用 thread.join()

        thread.start();
        thread.join();
        return b.get();
        

        缺点

        如果有数千条短信要发送,它会创建那么多线程。 这里没有使用线程创建,因为您可以传入线程本身来发送短信。

      3. 使用 Runnable 和 Future。

        一个。为每条短信创建一个 SendSms 对象,

        b.它将创建最多 10 个线程。

        c。 send SMS 和 getSMSdelivery 将是同步事件。因此,对于发送的每条短信,如果这是您的要求,您可以获得发送状态。

        import java.util.concurrent.ExecutionException;
        import java.util.concurrent.ExecutorService;
        import java.util.concurrent.Executors;
        import java.util.concurrent.Future;
        
        public class SendSms 
        {
            private static ExecutorService pool = Executors.newFixedThreadPool(10);
        
           public boolean submitSms(String message,String phNo)
           {        
              Runnable run = new SendSMSThread(message,phNo);
              Future future = pool.submit(run);
              try {
                  if(null ==future.get())
                  {
                      return true;
                  }
              } catch (InterruptedException | ExecutionException e) {
                  // SMS Sending failed.
                  e.printStackTrace();
                 return false;
              }
            return false;
            }
        
           private class SendSMSThread implements Runnable
           {
               String message;
               String phNo;
               public SendSMSThread(String message,String phNo)
               {
                   this.message = message;
                   this.phNo = phNo;
               }
               public void run()
               {
                   //Send SMS
               }
            }
        }
        
      4. 以上三个解决方案都是阻塞的。因此,它会使线程保持在 BLOCKING 状态,从而对系统的可扩展性构成重大威胁。

        一个。使用阻塞队列。

        b.对于每个 SMS 请求,将 SMSObject 添加到 BlockingQueue。

        c。使用线程池处理队列中的对象。

        d。成功发送 SMS 后,将结果保存到另一个数据结构中。

        e。使用线程池,从上述数据结构中读取数据并通知短信发送成功。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-08-22
        • 1970-01-01
        • 1970-01-01
        • 2013-03-11
        • 2018-06-03
        • 1970-01-01
        相关资源
        最近更新 更多