1、 作業系統的任務排程
在window和Linux作業系統中,任務排程采用時間片輪轉機制,因為CPU執行效率非常高,記憶體執行效率比較低,為了提高CPU使用率,采用時間片輪轉,就是一個任務執行一段時間之後強制暫停去執行下一個任務,每個任務輪流執行,被暫停的任務處于就緒狀态,等待下一個屬于它的時間片到來,這樣每個任務都得到執行,而并發的意思就是多個任務同時執行。
并行:是指多個處理器或者多核處理器同僚處理多個不同的任務。
并發:一個處理器同僚處理多個任務。
并發和并行與多線程的關系是:并行需要兩個或者兩個以上的線程運作在不同的處理器上,而并發可以再一個處理器上通過時間片輪轉進行切換。
2、程序線程定義
作業系統負責任務排程,資源配置設定和管理,統領整個計算機硬體,應用程式則是具有某種功能的程式,運作于作業系統之上。
程序:程序是具有獨立功能的程式在一個資料集上的一次動态執行過程,是作業系統進行資源配置設定和排程的一個獨立機關,是應用程式運作的載體。程序一般由程式、資料集合、和程序控制塊三部分組成。
程序是程式的一次執行,是臨時的有生命周期的,動态産生動态消亡,任何程序可以同其他程序一起并發執行,程序是系統進行資源配置設定和排程的獨立機關,程序由程式,資料和控制塊組成。
線程:線程的作用簡單來說是可以讓程序中的不同代碼塊同時執行,線程是程式執行的單一順序的控制流程,程式執行的最小單元,是處理器排程和分派的基本機關。各個線程之間共享程序的記憶體空間。一個線程由線程ID、目前指令指針PC、寄存器和堆棧組成。
3、android中的多程序通信方法
每個程序都對應虛拟機配置設定的一塊獨立的記憶體空間,不同的程序之間記憶體獨立,(每個應用程式就是一個程序,當然一個應用程式可以有多個程序)如果兩個程序之間需要共享資料,就需要用到IPC就是跨程序通信。
Android的SDK提供四種跨程序通信方式,對應四大元件。Activity可以跨程序調用其他應用程式的Activity,content Provider可以跨程序通路其他應用程式的的資料,另外broadcast可以向系統所有應用發送廣播,service之間可以通過AIDL實作程序間通信。
(1)Activity:Activity跨程序不需要制定Context對象和Activity的class對象,需要通路的是Activity所對赢得action,和URI,是Intent的第二個參數。
如:Intent callIntent = new Intent(Intent.ACTION_CALL,Uri.parse(“tel:123456”));
startActivity(callIntent);
(2)ContentProvider
Android應用程式需可以使用檔案或者Sqlite共享存儲資料,可以利用contentProvider進行增删查改,如音頻、視訊、聯系人資訊、通過這些ContentProvider可以擷取相應的資訊清單,這些清單以Cursor對象傳回。
(3)廣播
發送廣播需要調用sendBroadcast方法,該方法需要一個Intent對象,通過Intent可以發送,廣播需要的資料,利用廣播通信會有明顯的延時,并且因為廣播是向整個作業系統發送,容易出現被其他應用程式攔截的情況。
(4)service
service既不是線程也不是程序,如果需要執行耗時操作,需要新開一個線程實作,這個時候可以使用IntentService實作,因為IntentService總的HandAction實際上是一個線程可以處理耗時操作。
使用AIDL實際上是CS架構,這個時候如果需要回報資料,需要進行兩邊同時定義AIDL接口,然後進行資料的回傳。
4、AIDL通信
實作AIDL通信對于需要傳遞一個自定義對象的資料,需要序列化,序列化分為兩種方法Serializable和Parcelable。
4.1序列化的目的:
(1)永久儲存對象資料,将對象儲存在檔案或磁盤中
(2)通過序列化将對象資料,進行網絡傳輸,把對象資料轉換為位元組流方式
(3)将對象資料在程序間進行傳遞,在目前Activity中進行序列化操作寫入,在另一個中進行反序列化操作讀出。
(4)将資料儲存至資料庫和檔案中
(5)序列化隻針對對象不針對方法
(6)Intent之間傳遞資料,複雜的可以使用序列化操作。
4.2 android中實作序列化兩種方法。
(1)Serialization接口
寫一個實體類 Person,利用Java自帶的Serializable進行序列化
package com.amqr.serializabletest.entity;
import java.io.Serializable;
/**
* User: LJM
* Date&Time: 2016-02-22 & 14:16
* Describe: Describe Text
*/
public class Person implements Serializable{
private static final long serialVersionUID = ;
private String name;
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
使用,MainActivity和SecondActivity結合使用
MainActivity
package com.amqr.serializabletest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import com.amqr.serializabletest.entity.Person;
/**
* 進行Android開發的時候,我們都知道不能将對象的引用傳給Activities或者Fragments,
* 我們需要将這些對象放到一個Intent或者Bundle裡面,然後再傳遞。
*
*
* Android中Intent如果要傳遞類對象,可以通過兩種方式實作。
* 方式一:Serializable,要傳遞的類實作Serializable接口傳遞對象,
* 方式二:Parcelable,要傳遞的類實作Parcelable接口傳遞對象。
*
* Serializable(Java自帶):
* Serializable是序列化的意思,表示将一個對象轉換成可存儲或可傳輸的狀态。序列化後的對象可以在網絡上進行傳輸,也可以存儲到本地。
*
* Parcelable(android 專用):
* 除了Serializable之外,使用Parcelable也可以實作相同的效果,
* 不過不同于将對象進行序列化,Parcelable方式的實作原理是将一個完整的對象進行分解,
* 而分解後的每一部分都是Intent所支援的資料類型,這樣也就實作傳遞對象的功能了。
要求被傳遞的對象必須實作上述2種接口中的一種才能通過Intent直接傳遞。
*/
public class MainActivity extends Activity {
private TextView mTvOpenNew;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.mTvOpenNew).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent open = new Intent(MainActivity.this,SecondActivity.class);
Person person = new Person();
person.setName("一去二三裡");
person.setAge();
// 傳輸方式一,intent直接調用putExtra
// public Intent putExtra(String name, Serializable value)
open.putExtra("put_ser_test", person);
// 傳輸方式二,intent利用putExtras(注意s)傳入bundle
/**
Bundle bundle = new Bundle();
bundle.putSerializable("bundle_ser",person);
open.putExtras(bundle);
*/
startActivity(open);
}
});
}
}
SecondActivity
package com.amqr.serializabletest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;
import com.amqr.serializabletest.entity.Person;
/**
* User: LJM
* Date&Time: 2016-02-22 & 11:56
* Describe: Describe Text
*/
public class SecondActivity extends Activity{
private TextView mTvDate;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
mTvDate = (TextView) findViewById(R.id.mTvDate);
Intent intent = getIntent();
// 關鍵方法:getSerializableExtra ,我們的類是實作了Serializable接口的,是以寫這個方法獲得對象
// public class Person implements Serializable
Person per = (Person)intent.getSerializableExtra("put_ser_test");
//Person per = (Person)intent.getSerializableExtra("bundle_ser");
mTvDate.setText("名字:"+per.getName()+"\\n"
+"年齡:"+per.getAge());
}
}
連結:https://www.jianshu.com/p/a60b609ec7e7
(2)Parcelable接口
我們寫一個實體類,實作Parcelable接口,馬上就被要求
1、複寫describeContents方法和writeToParcel方法
2、執行個體化靜态内部對象CREATOR,實作接口Parcelable.Creator 。
也就是,随便一個類實作了Parcelable接口就一開始就會變成這樣子
Parcelable方式的實作原理是将一個完整的對象進行分解,而分解後的每一部分都是Intent所支援的資料類型,這樣也就實作傳遞對象的功能了。
public class Pen implements Parcelable{
private String color;
private int size;
protected Pen(Parcel in) {
color = in.readString();
size = in.readInt();
}
public static final Creator<Pen> CREATOR = new Creator<Pen>() {
@Override
public Pen createFromParcel(Parcel in) {
return new Pen(in);
}
@Override
public Pen[] newArray(int size) {
return new Pen[size];
}
};
@Override
public int describeContents() {
return ;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(color);
dest.writeInt(size);
}
}
系統已經幫我們做了很多事情,我們需要做的很簡單,就寫寫我們自己需要的構造方法,寫一下私有變量的get和set
大概變成這樣子:
package com.amqr.serializabletest.entity;
import android.os.Parcel;
import android.os.Parcelable;
/**
* User: LJM
* Date&Time: 2016-02-22 & 14:52
* Describe: Describe Text
*/
public class Pen implements Parcelable{
private String color;
private int size;
// 系統自動添加,給createFromParcel裡面用
protected Pen(Parcel in) {
color = in.readString();
size = in.readInt();
}
public static final Creator<Pen> CREATOR = new Creator<Pen>() {
/**
*
* @param in
* @return
* createFromParcel()方法中我們要去讀取剛才寫出的name和age字段,
* 并建立一個Person對象進行傳回,其中color和size都是調用Parcel的readXxx()方法讀取到的,
* 注意這裡讀取的順序一定要和剛才寫出的順序完全相同。
* 讀取的工作我們利用一個構造函數幫我們完成了
*/
@Override
public Pen createFromParcel(Parcel in) {
return new Pen(in); // 在構造函數裡面完成了 讀取 的工作
}
//供反序列化本類數組時調用的
@Override
public Pen[] newArray(int size) {
return new Pen[size];
}
};
@Override
public int describeContents() {
return ; // 内容接口描述,預設傳回0即可。
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(color); // 寫出 color
dest.writeInt(size); // 寫出 size
}
// ======分割線,寫寫get和set
//個人自己添加
public Pen() {
}
//個人自己添加
public Pen(String color, int size) {
this.color = color;
this.size = size;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
}
其實說起來Parcelable寫起來也不是很麻煩,在as裡面,我們的一個實體類寫好私有變量之後,讓這個類繼承自Parcelable,接下的步驟是:
1、複寫兩個方法,分别是describeContents和writeToParcel
2、執行個體化靜态内部對象CREATOR,實作接口Parcelable.Creator 。 以上這兩步系統都已經幫我們自動做好了
3、自己寫寫我們所需要的構造方法,變量的get和set
實作自Parcelable實體Bean已經寫好了,接下來我們結合MainActivity和ThirdActivity來使用以下:
MainActivity
package com.amqr.serializabletest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import com.amqr.serializabletest.entity.Pen;
import com.amqr.serializabletest.entity.Person;
/**
* 進行Android開發的時候,我們都知道不能将對象的引用傳給Activities或者Fragments,
* 我們需要将這些對象放到一個Intent或者Bundle裡面,然後再傳遞。
*
*
* Android中Intent如果要傳遞類對象,可以通過兩種方式實作。
* 方式一:Serializable,要傳遞的類實作Serializable接口傳遞對象,
* 方式二:Parcelable,要傳遞的類實作Parcelable接口傳遞對象。
*
* Serializable(Java自帶):
* Serializable是序列化的意思,表示将一個對象轉換成可存儲或可傳輸的狀态。序列化後的對象可以在網絡上進行傳輸,也可以存儲到本地。
*
* Parcelable(android 專用):
* 除了Serializable之外,使用Parcelable也可以實作相同的效果,
* 不過不同于将對象進行序列化,Parcelable方式的實作原理是将一個完整的對象進行分解,
* 而分解後的每一部分都是Intent所支援的資料類型,這樣也就實作傳遞對象的功能了。
要求被傳遞的對象必須實作上述2種接口中的一種才能通過Intent直接傳遞。
*/
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.mTvOpenNew).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent open = new Intent(MainActivity.this, SecondActivity.class);
Person person = new Person();
person.setName("一去二三裡");
person.setAge();
// 傳輸方式一,intent直接調用putExtra
// public Intent putExtra(String name, Serializable value)
open.putExtra("put_ser_test", person);
// 傳輸方式二,intent利用putExtras(注意s)傳入bundle
/**
Bundle bundle = new Bundle();
bundle.putSerializable("bundle_ser",person);
open.putExtras(bundle);
*/
startActivity(open);
}
});
// 采用Parcelable的方式
findViewById(R.id.mTvOpenThird).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent mTvOpenThird = new Intent(MainActivity.this,ThirdActivity.class);
Pen tranPen = new Pen();
tranPen.setColor("big red");
tranPen.setSize();
// public Intent putExtra(String name, Parcelable value)
mTvOpenThird.putExtra("parcel_test",tranPen);
startActivity(mTvOpenThird);
}
});
}
}
ThirdActivity
package com.amqr.serializabletest;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import com.amqr.serializabletest.entity.Pen;
/**
* User: LJM
* Date&Time: 2016-02-22 & 14:47
* Describe: Describe Text
*/
public class ThirdActivity extends Activity{
private TextView mTvThirdDate;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_third);
mTvThirdDate = (TextView) findViewById(R.id.mTvThirdDate);
// Intent intent = getIntent();
// Pen pen = (Pen)intent.getParcelableExtra("parcel_test");
Pen pen = (Pen)getIntent().getParcelableExtra("parcel_test");
mTvThirdDate = (TextView) findViewById(R.id.mTvThirdDate);
mTvThirdDate.setText("顔色:"+pen.getColor()+"\\n"
+"大小:"+pen.getSize());
}
}
連結:https://www.jianshu.com/p/a60b609ec7e7
(3)性能比較
parcelable性能強于serializable
(1)記憶體使用中強于後者
(2)後者序列化操作時候,會産生大量臨時變量,進而導緻GC頻繁調用,性能下降
(3)parcelable是以Ibinder為載體,記憶體上開銷較小。
(4)讀寫資料的時候parcelable是直接讀寫,而serializable是通過IO流形式讀寫如硬碟上。
當然在将資料持久化的時候,如把資料寫入硬碟的時候,仍然需要使用serializable。
4.3建立一個簡單的AIDL執行個體
首先,我們就在AS裡面建立一個aidl檔案(ps:現在AS建aidl不要求和java包名相同了):
package aidl;
interface IMyInterface {
String getInfor(String s);
}
可以看到,在這裡面我們就一個方法getInfor(String s),接受一個字元串參數,然後傳回一個字元串,相當的簡單。
接着你sync project一下就可以在app/generated/source/aidl/debug/aidl裡面發現由aidl檔案生成的java檔案了。點進去一看,可能你也被這個的類給吓住了,那現在我們就先不管它了。
然後就看看Service:
public class MyService extends Service {
public final static String TAG = "MyService";
private IBinder binder = new IMyInterface.Stub() {
@Override
public String getInfor(String s) throws RemoteException {
Log.i(TAG, s);
return "我是 Service 傳回的字元串";
}
};
@Overrid
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreat");
}
@Override
public IBinder onBind(Intent intent) {
return binder;
}
}
這裡我們寫了一個Service,看一下也比較簡單。先new了一IMyInterface.Stub()并把它向上轉型成了IBinder,最後在onBind方法中傳回回去。可能你注意到了,在IMyInterface.Stub()的内部我們重寫getInfor(String s) 方法,沒錯這就是我們 aidl檔案中定義的接口。
對了,因為我們希望看到的是跨程序通信,是以我們把MyService定義成新啟動一個程序:
<service
android:name=".server.MyService"
android:process="com.xu.remote" />
定義為啟動在新程序中,隻需要在AndroidMainfest.xml中聲明是加上一個process屬性即可,不過這裡有兩個地方值得注意:
1.元件預設的程序名就是包名;
2.定義新的程序名的時候需要以包的形式(eg: com.xu.aidl)。
接着,我們繼續向下看:
public class MainActivity extends AppCompatActivity {
public final static String TAG = "MainActivity";
private IMyInterface myInterface;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myInterface = IMyInterface.Stub.asInterface(service);
Log.i(TAG, "連接配接Service 成功");
try {
String s = myInterface.getInfor("我是Activity傳來的字元串");
Log.i(TAG, "從Service得到的字元串:" + s);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e(TAG, "連接配接Service失敗");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startAndBindService();
}
private void startAndBindService() {
Intent service = new Intent(MainActivity.this, MyService.class);
//startService(service);
bindService(service, serviceConnection, Context.BIND_AUTO_CREATE);
}
}
在onCreate(Bundle savedInstanceState)中,我們調用了自己定義的一個方法startAndBindService(),這個方法裡面我們生成了一個Intent,然後 bindService了這個Intent傳入了三個參數分别是Intent、ServiceConnection、Flag。
Intent我們就不用說了,我們看看後面兩個參數:
在Activity中,我們new了一個ServiceConnection并實作了他的兩個方法onServiceConnected、onServiceDisconnected。在onServiceConnected中我們通過IMyInterface.Stub.asInterface(service)把傳來的IBinder轉換成了我們定義的IMyInterface。然後我們調用了getInfor方法,傳遞了個字元串和擷取從MyService傳來的字元串,并且列印了Log。
對于我們傳的Context.BIND_AUTO_CREATE的意思就是說:如果綁定Service的時候,Service還沒有被建立,就建立它。
大緻的實作流程就是,先定義一個AIDL接口,然後進行再service中的stub中實作接口中的方法,然後在client中實作通過ServiceConnection連接配接,并且在asInterface中調用方法。
4.4 aidl中的接口解析
Binder工作機制由用戶端、Binder、服務端組成,用戶端和服務端都是通過Binder進行交流。
Stub類是繼承自Binder類,Stub類就是Binder的執行個體,在服務端一般會執行個體化一個Binder對象,用戶端在Service中綁定的時候可以擷取這個Stub(Binder)
通過asInterface()方法擷取它的執行個體對象。如果用戶端和服務端在同一程序下,那麼asInterface()将傳回Stub對象本身,否則傳回Stub.Prox對象。
也就是說asInterface()傳回的對象有兩種可能(實際上有三種,還有一種是null),Stub和Stub.Proxy。它們有什麼差別呢?
- 如果在同一個程序下的話,那麼asInterface()将傳回服務端的Stub對象本身,因為此時根本不需要跨進稱通信,那麼直接調用Stub對象的接口就可以了,傳回的實作就是服務端的Stub實作,也就是根本沒有跨程序通信;
- 如果不是同一個程序,那麼asInterface()傳回是Stub.Proxy對象,該對象持有着遠端的Binder引用,因為現在需要跨程序通信,是以如果調用Stub.Proxy的接口的話,那麼它們都将是IPC調用,它會通過調用transact方法去與服務端通信。
- Stub是服務端實作的存根,而Proxy則是Stub的代理。
5、多線程實作方法
java實作多線程實作方式主要有四種:繼承Thread類、實作Runnable接口、實作Callable接口通過FutureTask包裝器建立Thread線程、使用ExecutorService、Callble、Future實作有傳回結果的多線程。
(1)繼承Thread類建立線程
Thread本質上是實作Runnable接口的一個執行個體,代表一個線程的執行個體。啟動線程的唯一方法就是通過Thread類的start()執行個體方法。start()方法是一個native方法,他啟動一個新縣城,并執行run()方法。直接繼承Thread,然後重寫run()方法啟動新線程即可執行自定義的run()方法。
public class MyThread extends Thread{
public void run(){
//邏輯
}
}
MyThead myThead1 = new MyThread();
MyThread myThread2 = new MyThread();
myThread1.start();
myThread2.start();
(2)實作Runnable 接口建立線程
如果自己已經extends一個類,就無法直接extends Thread ,此時可以實作一個Runnable接口:
public class MyThread extends OhterClass implements Runnable{
public void run(){
//邏輯
}
}
MyThread myThread = new MyThread();
Thread thread = new Thread(myThread);
thread.start();
(3)實作Callable接口通過FutureTask包裝器來建立愛你Thread線程
Callable接口定義:
public class SomeCallable<V> extends OtherClass implements Callable<V> {
@Override
public V call() throws Exception {
// TODO Auto-generated method stub
return null;
}
}
Callable<V> oneCallable = new SomeCallable<V>();
//由Callable<Integer>建立一個FutureTask<Integer>對象:
FutureTask<V> oneTask = new FutureTask<V>(oneCallable);
//注釋:FutureTask<Integer>是一個包裝器,它通過接受Callable<Integer>來建立,它同時實作了Future和Runnable接口。
//由FutureTask<Integer>建立一個Thread對象:
Thread oneThread = new Thread(oneTask);
oneThread.start();
//至此,一個線程就建立完成了。
4、使用ExecutorService、Callable、Future實作有傳回結果的線程
ExecutorService、Callable、Future三個接口實際上都是屬于Executor架構。傳回結果的線程是在JDK1.5中引入的新特征,有了這種特征就不需要再為了得到傳回值而大費周折了。而且自己實作了也可能漏洞百出。
可傳回值的任務必須實作Callable接口。類似的,無傳回值的任務必須實作Runnable接口。
執行Callable任務後,可以擷取一個Future的對象,在該對象上調用get就可以擷取到Callable任務傳回的Object了。
注意:get方法是阻塞的,即:線程無傳回結果,get方法會一直等待。
再結合線程池接口ExecutorService就可以實作傳說中有傳回結果的多線程了。
下面提供了一個完整的有傳回結果的多線程測試例子,在JDK1.5下驗證過沒問題可以直接使用。代碼如下:
import java.util.concurrent.*;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
/**
* 有傳回值的線程
*/
@SuppressWarnings("unchecked")
public class Test {
public static void main(String[] args) throws ExecutionException,
InterruptedException {
System.out.println("----程式開始運作----");
Date date1 = new Date();
int taskSize = 5;
// 建立一個線程池
ExecutorService pool = Executors.newFixedThreadPool(taskSize);
// 建立多個有傳回值的任務
List<Future> list = new ArrayList<Future>();
for (int i = 0; i < taskSize; i++) {
Callable c = new MyCallable(i + " ");
// 執行任務并擷取Future對象
Future f = pool.submit(c);
// System.out.println(">>>" + f.get().toString());
list.add(f);
}
// 關閉線程池
pool.shutdown();
// 擷取所有并發任務的運作結果
for (Future f : list) {
// 從Future對象上擷取任務的傳回值,并輸出到控制台
System.out.println(">>>" + f.get().toString());
}
Date date2 = new Date();
System.out.println("----程式結束運作----,程式運作時間【"
+ (date2.getTime() - date1.getTime()) + "毫秒】");
}
}
class MyCallable implements Callable<Object> {
private String taskNum;
MyCallable(String taskNum) {
this.taskNum = taskNum;
}
public Object call() throws Exception {
System.out.println(">>>" + taskNum + "任務啟動");
Date dateTmp1 = new Date();
Thread.sleep(1000);
Date dateTmp2 = new Date();
long time = dateTmp2.getTime() - dateTmp1.getTime();
System.out.println(">>>" + taskNum + "任務終止");
return taskNum + "任務傳回運作結果,目前任務時間【" + time + "毫秒】";
}
}
代碼說明:
上述代碼中Executors類,提供了一系列工廠方法用于建立線程池,傳回的線程池都實作了ExecutorService接口。
public static ExecutorService newFixedThreadPool(int nThreads)
建立固定數目線程的線程池。
public static ExecutorService newCachedThreadPool()
建立一個可緩存的線程池,調用execute 将重用以前構造的線程(如果線程可用)。如果現有線程沒有可用的,則建立一個新線程并添加到池中。終止并從緩存中移除那些已有 60 秒鐘未被使用的線程。
public static ExecutorService newSingleThreadExecutor()
建立一個單線程化的Executor。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
建立一個支援定時及周期性的任務執行的線程池,多數情況下可用來替代Timer類。
ExecutoreService提供了submit()方法,傳遞一個Callable,或Runnable,傳回Future。如果Executor背景線程池還沒有完成Callable的計算,這調用傳回Future對象的get()方法,會阻塞直到計算完成。
參考:https://www.cnblogs.com/felixzh/p/6036074.html
https://blog.csdn.net/baidu_29094221/article/details/78852998
https://blog.csdn.net/yan8024/article/details/6444368
https://blog.csdn.net/aboy123/article/details/38307539/
https://blog.csdn.net/wangchunlei123/article/details/51345130
https://www.cnblogs.com/yezhennan/p/5527506.html
大緻就寫到這裡吧,知識越擴充越多,本人技術小白一個,有錯誤地地方,多多指點。