一、操作系統(tǒng)中線程和進程的概念
現(xiàn)在的操作系統(tǒng)是多任務操作系統(tǒng)。多線程是實現(xiàn)多任務的一種方式。
進程是指一個內(nèi)存中運行的應用程序,每個進程都有自己獨立的一塊內(nèi)存空間,一個進程中可以啟動多個線程。比如在Windows系統(tǒng)中,一個運行的exe就是一個進程。
線程是指進程中的一個執(zhí)行流程,一個進程中可以運行多個線程。比如java.exe進程中可以運行很多線程。線程總是屬于某個進程,進程中的多個線程共享進程的內(nèi)存。
二、為什么要使用多線程
舉個例子就如同節(jié)假日的公路,如果只有一條通行道的好就會出現(xiàn)塞車的情況,然后就會使整條道路堵塞不能通行。如果有多條馬路的話,即使有一條馬路堵塞很擁擠我可以先擇其他馬路去走,那么我通行的時間就沒有受到影響。
線程的作用就是如此,我們可以把需要耗時的操作放到子線程里面去,等子線程完成任務時再在主線程做出相應的響應。
三、線程的狀態(tài)與生命周期
Java語言使用Thread類及其子類的對象來表示線程,新建的線程在它的一個完整生命周期中通常要經(jīng)歷一下四種狀態(tài)。
- 新建
- 運行
- 中斷
- 死亡
在Java中有4中出現(xiàn)中斷的原因:1. JVM將CPU資源從當前線程切換給其他線程。2. 線程使用CPU資源間使用了sleep。3. 線程使用CPU期間執(zhí)行wait。 4. 線程使用CPU資源期間,執(zhí)行某個操作進入阻塞。
四、常見更新UI的方式
在本例中我只使用了兩種方式實現(xiàn)UI的更新即:handler+Thread和用runOnUiThread方法。
從實現(xiàn)原理上,兩者別無二致,runOnUiThread也是借助Handler實現(xiàn)的。
對于使用場景,runOnUiThread用法簡單,并且共享了同一個Handler,用起來高效、方便。另外,如果在主線程中直接調(diào)用,runOnUiThread也可以判斷并立即執(zhí)行,不再推入消息隊列。而Handler由于更加基礎,所以可定制性要比runOnUiThread強,可以實現(xiàn)標記、延時等功能,并且可以推入其他消息循環(huán)線程而非主線程。
使用runOnUiThread方法
public class TabletimeActivity2 extends AppCompatActivity {
private String mSemester;
private String mClassName;
private String strJson;
private GridView mGridView;
private final String url ="http://192.168.3.151:8080/Educational/GetJson";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tabletime2);
getLogin();
Request();
}
public void getLogin(){
mGridView= (GridView) findViewById(R.id.gridview);
Intent Intent=getIntent();
mSemester=Intent.getStringExtra("Semester");
mClassName=Intent.getStringExtra("ClassName");
ClassBean Cbean=new ClassBean();
Cbean.setClassName(mClassName);
Cbean.setSemester(mSemester);
Gson gson = new Gson();
strJson = gson.toJson(Cbean);
}
public void Request(){
new Thread(new Runnable() {
@Override
public void run() {
OkHttpClient client = new OkHttpClient();
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
//把請求的內(nèi)容字符串轉換 為json
RequestBody body = RequestBody.create(JSON, strJson);
Log.i("Json",strJson);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = null;
try {
response = client.newCall(request).execute();
String result = response.body().string();
if (result!=null){
Gson gson=new Gson();
List<Table> tables = gson.fromJson(result, new
TypeToken<List<Table>>()
{}.getType());
InitGridView(tables);
}
} catch (IOException e) {
e.printStackTrace();
Log.i("錯誤:", e.toString());
}
}
}).start();
}
private void InitGridView(final List<Table> tables) {
runOnUiThread(new Runnable() {
@Override
public void run() {
List<String> strList = new ArrayList<String>();
for (Table table : tables) {
strList.add(table.getSection());
strList.add(table.getOne());
strList.add(table.getTwo());
strList.add(table.getThree());
strList.add(table.getFour());
strList.add(table.getFive());
strList.add(table.getSix());
strList.add(table.getSeven());
}
MyAdapter adapter = new MyAdapter(TabletimeActivity2.this, strList);
mGridView.setAdapter(adapter);
}
});
}
}
向服務器發(fā)送申請并返回數(shù)據(jù)屬于一個耗時操作,我們應該把它放在一個子線程中,開啟一個Thread發(fā)送申請并得到數(shù)據(jù)后,利用runOnUiThread(Runnable)把更新ui的代碼創(chuàng)建在Runnable中,然后在需要更新ui時,就能在ui程序中被調(diào)用。如果當前線程是UI線程,那么行動是立即執(zhí)行。如果當前線程不是UI線程,操作是發(fā)布到事件隊列的UI線程。
handler+Thread
public class RequestOrResponse {
private final String url ="http://192.168.3.151:8080/Educational/GetJson";
private String StrJson;
public void Request(final String Strjson) throws IOException {
new Thread(new Runnable() {
@Override
public void run() {
OkHttpClient client = new OkHttpClient();
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
//把請求的內(nèi)容字符串轉換 為json
RequestBody body = RequestBody.create(JSON, Strjson);
Log.i("Json",Strjson);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = null;
try {
response = client.newCall(request).execute();
String result = response.body().string();
if (result!=null){
Message message=new Message();
message.what=1;
message.getData().putString("result",result);
handler.sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
Log.i("錯誤:", e.toString());
}
}
}).start();
}
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
if (msg.what==1){
StrJson=msg.getData().getString("result");
Log.i("result",StrJson);
}
}
};
public String getStrJson(){
return StrJson;
}
}
在申請請求得到響應時,創(chuàng)建一個Message發(fā)送到handler,然后在UI線程中創(chuàng)建一個handler,取到子線程的Message。然后就可以在其他Activity中調(diào)用該類的方法得到返回的數(shù)據(jù)。
-個人總結-
我對線程的了解還是太少,因為剛接觸總是覺得它難然后就很少用它。在調(diào)試時經(jīng)常出現(xiàn)線程堵塞的情況,還不懂怎么入手解決。想得到子線程的值還可以用回調(diào)函數(shù)這個方法來實現(xiàn),線程的實現(xiàn)原理只是了解皮毛。