一、操作系统中线程和进程的概念
现在的操作系统是多任务操作系统。多线程是实现多任务的一种方式。
进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。比如在Windows系统中,一个运行的exe就是一个进程。
线程是指进程中的一个执行流程,一个进程中可以运行多个线程。比如java.exe进程中可以运行很多线程。线程总是属于某个进程,进程中的多个线程共享进程的内存。
二、为什么要使用多线程
举个例子就如同节假日的公路,如果只有一条通行道的好就会出现塞车的情况,然后就会使整条道路堵塞不能通行。如果有多条马路的话,即使有一条马路堵塞很拥挤我可以先择其他马路去走,那么我通行的时间就没有受到影响。
线程的作用就是如此,我们可以把需要耗时的操作放到子线程里面去,等子线程完成任务时再在主线程做出相应的响应。
三、线程的状态与生命周期
Java语言使用Thread类及其子类的对象来表示线程,新建的线程在它的一个完整生命周期中通常要经历一下四种状态。
- 新建
- 运行
- 中断
- 死亡
在Java中有4中出现中断的原因:1. JVM将CPU资源从当前线程切换给其他线程。2. 线程使用CPU资源间使用了sleep。3. 线程使用CPU期间执行wait。 4. 线程使用CPU资源期间,执行某个操作进入阻塞。
四、常见更新UI的方式
在本例中我只使用了两种方式实现UI的更新即:handler+Thread和用runOnUiThread方法。
从实现原理上,两者别无二致,runOnUiThread也是借助Handler实现的。
对于使用场景,runOnUiThread用法简单,并且共享了同一个Handler,用起来高效、方便。另外,如果在主线程中直接调用,runOnUiThread也可以判断并立即执行,不再推入消息队列。而Handler由于更加基础,所以可定制性要比runOnUiThread强,可以实现标记、延时等功能,并且可以推入其他消息循环线程而非主线程。
使用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");
//把请求的内容字符串转换 为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 tables = gson.fromJson(result, new
TypeToken>()
{}.getType());
InitGridView(tables);
}
} catch (IOException e) {
e.printStackTrace();
Log.i("错误:", e.toString());
}
}
}).start();
}
private void InitGridView(final List tables) {
runOnUiThread(new Runnable() {
@Override
public void run() {
List strList = new ArrayList();
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);
}
});
}
}
向服务器发送申请并返回数据属于一个耗时操作,我们应该把它放在一个子线程中,开启一个Thread发送申请并得到数据后,利用runOnUiThread(Runnable)把更新ui的代码创建在Runnable中,然后在需要更新ui时,就能在ui程序中被调用。如果当前线程是UI线程,那么行动是立即执行。如果当前线程不是UI线程,操作是发布到事件队列的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");
//把请求的内容字符串转换 为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;
}
}
在申请请求得到响应时,创建一个Message发送到handler,然后在UI线程中创建一个handler,取到子线程的Message。然后就可以在其他Activity中调用该类的方法得到返回的数据。
-个人总结-
我对线程的了解还是太少,因为刚接触总是觉得它难然后就很少用它。在调试时经常出现线程堵塞的情况,还不懂怎么入手解决。想得到子线程的值还可以用回调函数这个方法来实现,线程的实现原理只是了解皮毛。