標籤:line .exe lan start pop asm executor this 順序
接上文
前文中的遺留問題
對於Java多線程的理解。我曾經只局限於實現Runnable介面或者繼承Thread類,然後重寫run()方法,最後start()調用就算完事。可是一旦涉及死結以及對共用資源的訪問和隨時監控線程的狀態和運行順序和線程返回值等就不行了。
Callable 和 Future 簡單介紹
Callable介面代表一段能夠調用並返回結果的代碼;Future介面表示是運行非同步任務時的狀態、返回值等資訊。所以說Callable用於產生結果,Future用於擷取結果。
1. Callable
Callable 是一個介面,它僅僅包括一個call()方法。Callable是一個返回結果而且可能拋出異常的任務。
為了便於理解,我們能夠將Callable比作一個Runnable介面,而Callable的call()方法則類似於Runnable的run()方法。
Callable的原始碼例如以下:
<span style="font-size:18px;">publi cinterface Callable<V> { V call() throws Exception;}</span>
2. Future
Future 是一個介面。它用於表示非同步計算的結果。提供了檢查計算是否完畢的方法,以等待計算的完畢,並擷取計算的結果。
Future的原始碼例如以下:
<span style="font-size:18px;">public interface Future<V> { // 試圖取消對此任務的運行。 boolean cancel(boolean mayInterruptIfRunning)//假設在任務正常完畢前將其取消,則返回 true。 boolean isCancelled()//假設任務已完畢,則返回 true。 boolean isDone()//如有必要,等待計算完畢,然後擷取其結果。 V get() throws InterruptedException,ExecutionException;//如有必要,最多等待為使計算完畢所給定的時間之後,擷取其結果(假設結果可用)。 V get(long timeout, TimeUnitunit) throws InterruptedException,ExecutionException, TimeoutException;}</span>
示範範例的Callable和Future的基本使用方法
我們先通過一個示範範例看看Callable和Future的基本使用方法
<span style="font-size:18px;">importjava.util.concurrent.Callable;importjava.util.concurrent.Future;importjava.util.concurrent.Executors;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.ExecutionException; classMyCallable implements Callable { @Override public Integer call() throws Exception { int sum = 0; // 運行任務 for (int i=0; i<100; i++) sum += i; //return sum; return Integer.valueOf(sum); }} publicclass CallableTest1 { public static void main(String[] args) throws ExecutionException,InterruptedException{ //建立一個線程池 ExecutorService pool =Executors.newSingleThreadExecutor(); //建立有傳回值的任務 Callable c1 = new MyCallable(); //運行任務並擷取Future對象 Future f1 = pool.submit(c1); // 輸出結果 System.out.println(f1.get()); //關閉線程池 pool.shutdown(); }}</span>
執行結果:
4950
結果說明:
在主線程main中,通過newSingleThreadExecutor()建立一個線程池。接著建立Callable對象c1。然後再通過pool.submit(c1)將c1提交到線程池中進行處理。而且將返回的結果儲存到Future對象f1中。
然後,我們通過f1.get()擷取Callable中儲存的結果;最後通過pool.shutdown()關閉線程池。
回到主題:調用查詢手機號歸屬地的webservice
事實上通過上面的簡單範例,全然能夠將通過Runnable介面或者Thread類實現的線程代碼,改動成Callable和Future實現的線程。
<span style="font-size:18px;">public class Main Activity extends Activity { public static final String TAG ="webService_pj"; private EditText phoneSecEditText; private TextView resultView; private Button queryButton; @Override public void onCreate(BundlesavedInstanceState) { // StrictMode.setThreadPolicy(newStrictMode.ThreadPolicy.Builder()// .detectDiskReads().detectDiskWrites().detectNetwork()// .penaltyLog().build());// // StrictMode.setVmPolicy(newStrictMode.VmPolicy.Builder()// .detectLeakedSqlLiteObjects().penaltyLog().penaltyDeath()// .build()); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); phoneSecEditText = (EditText)findViewById(R.id.phone_sec); resultView = (TextView)findViewById(R.id.result_text); queryButton = (Button)findViewById(R.id.query_btn); queryButton.setOnClickListener(newOnClickListener() { @Override public void onClick(View v) { Log.i(TAG,"MainActivity線程ID:"+Thread.currentThread().getId()); // 手機號碼(段) String phoneSec =phoneSecEditText.getText().toString().trim(); // 簡單推斷使用者輸入的手機號碼(段)是否合法 if("".equals(phoneSec) || phoneSec.length() < 7) { // 給出錯誤提示 phoneSecEditText.setError("您輸入的手機號碼(段)有誤。"); phoneSecEditText.requestFocus(); // 將顯示查詢結果的TextView清空 resultView.setText(""); return; } // 命名空間 String nameSpace = "http://WebXml.com.cn/"; // 調用的方法名稱 String methodName ="getMobileCodeInfo"; // EndPoint String endPoint = "http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx"; // SOAP Action String soapAction = "http://WebXml.com.cn/getMobileCodeInfo"; // method params and values ArrayList<String> params= new ArrayList<String>(); ArrayList<Object> vals =new ArrayList<Object>(); params.add("mobileCode"); params.add("userId"); vals.add(phoneSec); vals.add(""); //通過Callable和Future建立線程。調用WebService//建立有傳回值的任務 CallableThread callable = newCallableThread(nameSpace,methodName,endPoint,soapAction,params,vals); // 建立一個線程池 ExecutorServiceexecutor=Executors.newCachedThreadPool(); //運行任務並擷取Future對象 Future<String>future = executor.submit(callable); try {//輸出結果resultView.setText(future.get()); //關閉線程池executor.shutdown();}catch (InterruptedException e) {e.printStackTrace();}catch (ExecutionException e) {e.printStackTrace();} } }); } private class CallableThread implementsCallable<String> { private String nameSpace; private String methodName; private String endPoint; private String soapAction; private ArrayList<String> params; private ArrayList<Object> vals; public CallableThread(StringnameSpace, String methodName, StringendPoint, String soapAction, ArrayList<String> params,ArrayList<Object> vals){ this.nameSpace = nameSpace; this.methodName = methodName; this.endPoint = endPoint; this.soapAction = soapAction; this.params = params; this.vals = vals; } //須要實現Callable的Call方法 public String call() throws Exception{ // 這種方法的實現見上篇文章或者原始碼 return getRemoteInfo(nameSpace,methodName, endPoint, soapAction,params,vals); } } </span>
至此,Android調用Webservice就完美的完畢了。
原始碼下載
http://download.csdn.net/detail/tcl_6666/7365341
Android平台叫用Web Service:線程傳回值