Android 多线程 和异步的实践:跳转,同步显示时间,倒计时的实现,知识点
2015-10-17 10:37
941 查看
Android 多线程 和异步的实践
模拟引导页,数秒后转向新的页面
从主mainactiyity 到newpager 写了两种启动模式
先写 布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="24sp"
android:text="3S后跳转" />
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@drawable/aa"/>
</LinearLayout>
实现代码
package com.example.theadtest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends Activity {
private Handler mHandler;
Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// mHandler.postDelayed(new mythread(), 3000);//引导画面停留 6-8S
new Thread(new mythread()).start();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
class mythread implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
intent = new Intent(getApplicationContext(),
NewPagerActivity.class);
startActivity(intent);//启动方法 不属于UI
}
}
class MyThd extends Thread{
@Override
public void run() {
super.run();
long stime=System.currentTimeMillis();
//此处是逻辑计算加载资源时间 是否6S
long etime=System.currentTimeMillis();
long runtime=etime-stime;
try {
if (6000>runtime) {
Thread.sleep(6000-runtime);//一般定义为常量
}
else Thread.sleep(runtime);//一般定义为常量
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
在新的页面
有一个倒计时 ,有一个同步显示的时间,还有一个计算距离某天还有多久
同样写了两个线程启动的方法 实现runable接口和 继承Thread 重写run的区别
启动 new继承类的start()方法 重建接口实现Runable的启动方式newthread (有一个runable参数的构造方法任务new Thread(new 自定义实现的的runnable).start();
区别:1.第一种是继承的关系单继承,第二种是实现接口的关系可以多个2.任务写死在线程,不能复用,但是实现接口的可以复用,多个线程共用一个任务,用runnable
在非UI 线程中不可以操作UI
为什么要使用多线程?
响应时间5s 弹出对话框 ANR错误 application Not responsibding
原因:1.主线程5秒内没有响应输入事件2. BroadcastReceiver没有在10秒内完成返回。
根本原因主线程被阻塞,解决办法:将耗时操作放在异步的子线程中处理。
如 1.数据库的大数据量操作2.大文件的I/O操作
1. 网络操作。4复杂运算
子线程和主线程的通信发送Message是处理数据数据是绑定在message
通过Handler (处理机的意思)类作为通道负责发送和接收 在不同的线程间进行通信
Handler 的一个方法 obtainMessage();唯一性
可传递类型: arg1 .arg2 整形一般用来传递 简单的熟知数据
What 整形
Obj 对象数据 主要的数据绑定方式
Handler 发送 sendMessage() 接收handleMessage()
步骤
1. 构建一个Handler
2. 在需要通信的时候创建Message
3. 通过Handler 发送Message
4. 通过Handler 接收Message
Private Handler handle=new Handler ();
在线程中通讯处创建Message msg=new Message() {
加花括号就是重写其中的方法
写在主线程中 可以接受消息后 处理UI 需要重写private Handler
handler=new
Handler()
{
@Override
public
void handleMessage(Messagemsg) {
}
};
Asytask 异步任务 泛型参数内部方法 启动
比handler 更轻量级使用简单的 异步处理
参数可以是Java 任意类数据类型如果不需要参数 可以传入void
Params 启动任务执行的输入参数,比如http 请求的URL
Progress 后台任务的百分比 用于线程执行的UI 交互
Result 后台执行的最终返回结果
内部方法
OnPreExecute() 当前任务执行之前 调用此方法
doInBackground(Params) 后台执行 比较耗时的操作放在此处
onProgressUpdate(Progress) 显示进度
onPostExecute(Result) 任务执行完 调用的方法 任务执行的结果作为参数
接程序代码
新的页面 布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/text_display"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/hello_world" />
<Button
android:id="@+id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="点击开始倒计时"
/>
<TextView
android:gravity="center_horizontal"
android:id="@+id/text_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="当前时间" />
<TextView
android:id="@+id/tag_time"
android:gravity="center_horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="距离还有" />
<TextView
android:gravity="center_horizontal"
android:id="@+id/dao_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="24sp"
android:text="倒计时" />
</LinearLayout>
java代码
package com.example.theadtest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import android.R.integer;
import android.app.Activity;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.
4000
Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class NewPagerActivity extends Activity {
private TextView text_display, tag_time, text_time, dao_time;
private Button btn;
private Handler handler;
private static boolean state = false;
private static final String TIME_STRING = "2015-10-31-23-59-59";//把目标截止时间定义为常量,方便修改
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_pager);
text_time = (TextView) findViewById(R.id.text_time);
text_display = (TextView) findViewById(R.id.text_display);
dao_time = (TextView) findViewById(R.id.dao_time);
tag_time = (TextView) findViewById(R.id.tag_time);
btn = (Button) findViewById(R.id.btn);
tag_time.setText("距离" + TIME_STRING);
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
switch (msg.what) {
case 0:
String stime = msg.obj.toString();
text_time.setText(stime);
break;
case 1:
String s1 = msg.obj.toString();
if (Integer.parseInt(s1) <= 10) {
text_display.setTextColor(Color.CYAN);
text_display.setText(s1);
if (Integer.parseInt(s1) == 0) {
text_display.setText("Duang!!!!");
}
} else
text_display.setText(s1);
break;
default:
break;
}
}
};
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
new Mytime().start();
new Thread(new MyClick()).start();
// 开启异步任务
MyTask task = new MyTask();
task.execute();
}
});
}
class MyTask extends AsyncTask<Integer, Integer, Boolean> {
// 参数,对象类型1,启动的初始化数据 2,异步任务进度交互的数据 3,运行结果
/**
* @Override 即将启动的时候触发 一般用于准备工作
*/
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
dao_time.setText("-----开始!");// 纯属测试用的无意义
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.e("", "------------onPreExecute");
}
/**
* @Override
* 在异步任务运行个过程中 与UI交互的方法
*/
protected void onProgressUpdate(Integer... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
int timespan = values[0] / 1000;
long day = timespan / 86400;
long hour = timespan / 3600 - day * 24;
long min = timespan / 60 - hour * 60 - day * 24 * 60;
long sec = timespan % 60;
String txtString = "还有" + day + "天" + hour + "小时" + min + "分" + sec
+ "秒";
dao_time.setText(txtString);
}
/**
* @Override
* 惟一一个非UI线程运行的方法 主要处理异步任务
*/
protected Boolean doInBackground(Integer... params) {
int timespan = 0;
// 自定义时间格式
SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
// 根据定义state状态判定activity是否被销毁,否则可能,返回了,这个异步任务还在执行。
while (true && !state) {
try {
Thread.sleep(1000);
long endDate = s.parse(TIME_STRING).getTime();
long nowDate = System.currentTimeMillis();
timespan = (int) (endDate - nowDate);
if (timespan <= 0) {
return true;
}
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
publishProgress(timespan);
}
return true;
}
/**
* @Override 异步任务运行完毕后触发
*/
protected void onPostExecute(Boolean result) {
// TODO Auto-generated method stub
Log.e("", "------------onPostExecute");
if (result = true) {
dao_time.setText("活动倒计时结束");
Log.e("", "------------结束");
}
super.onPostExecute(result);
}
}
// Thread 使用 继承
class Mytime extends Thread {
public void run() {
while (true && !state) {
try {
Message msg = Message.obtain();
String s = new SimpleDateFormat("yyyy年-MM月-dd日-HH时-mm分-ss秒")
.format(System.currentTimeMillis());
msg.obj = "当前时间" + s;
msg.what = 0;
handler.sendMessage(msg);
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
// 实现接口
class MyClick implements Runnable {
public void run() {
try {
for (int i = 10; i >= 0; i--) {
Message msg = Message.obtain();
msg.obj = i;
msg.what = 1;
handler.sendMessage(msg);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* @Override
* activity销毁,改变state 异步里的doInBackground方法终止 返回true
*/
protected void onDestroy() {
// TODO Auto-generated method stub
state = true;
Log.e("", "------------onDestroy");
super.onDestroy();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.new_pager, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
截图如下,显示最后相加少了一秒,应该是,当前正在进行的那一秒!
模拟引导页,数秒后转向新的页面
从主mainactiyity 到newpager 写了两种启动模式
先写 布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="24sp"
android:text="3S后跳转" />
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@drawable/aa"/>
</LinearLayout>
实现代码
package com.example.theadtest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends Activity {
private Handler mHandler;
Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// mHandler.postDelayed(new mythread(), 3000);//引导画面停留 6-8S
new Thread(new mythread()).start();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
class mythread implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
intent = new Intent(getApplicationContext(),
NewPagerActivity.class);
startActivity(intent);//启动方法 不属于UI
}
}
class MyThd extends Thread{
@Override
public void run() {
super.run();
long stime=System.currentTimeMillis();
//此处是逻辑计算加载资源时间 是否6S
long etime=System.currentTimeMillis();
long runtime=etime-stime;
try {
if (6000>runtime) {
Thread.sleep(6000-runtime);//一般定义为常量
}
else Thread.sleep(runtime);//一般定义为常量
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
在新的页面
有一个倒计时 ,有一个同步显示的时间,还有一个计算距离某天还有多久
同样写了两个线程启动的方法 实现runable接口和 继承Thread 重写run的区别
启动 new继承类的start()方法 重建接口实现Runable的启动方式newthread (有一个runable参数的构造方法任务new Thread(new 自定义实现的的runnable).start();
区别:1.第一种是继承的关系单继承,第二种是实现接口的关系可以多个2.任务写死在线程,不能复用,但是实现接口的可以复用,多个线程共用一个任务,用runnable
在非UI 线程中不可以操作UI
为什么要使用多线程?
响应时间5s 弹出对话框 ANR错误 application Not responsibding
原因:1.主线程5秒内没有响应输入事件2. BroadcastReceiver没有在10秒内完成返回。
根本原因主线程被阻塞,解决办法:将耗时操作放在异步的子线程中处理。
如 1.数据库的大数据量操作2.大文件的I/O操作
1. 网络操作。4复杂运算
子线程和主线程的通信发送Message是处理数据数据是绑定在message
通过Handler (处理机的意思)类作为通道负责发送和接收 在不同的线程间进行通信
Handler 的一个方法 obtainMessage();唯一性
可传递类型: arg1 .arg2 整形一般用来传递 简单的熟知数据
What 整形
Obj 对象数据 主要的数据绑定方式
Handler 发送 sendMessage() 接收handleMessage()
步骤
1. 构建一个Handler
2. 在需要通信的时候创建Message
3. 通过Handler 发送Message
4. 通过Handler 接收Message
Private Handler handle=new Handler ();
在线程中通讯处创建Message msg=new Message() {
加花括号就是重写其中的方法
写在主线程中 可以接受消息后 处理UI 需要重写private Handler
handler=new
Handler()
{
@Override
public
void handleMessage(Messagemsg) {
}
};
Asytask 异步任务 泛型参数内部方法 启动
比handler 更轻量级使用简单的 异步处理
参数可以是Java 任意类数据类型如果不需要参数 可以传入void
Params 启动任务执行的输入参数,比如http 请求的URL
Progress 后台任务的百分比 用于线程执行的UI 交互
Result 后台执行的最终返回结果
内部方法
OnPreExecute() 当前任务执行之前 调用此方法
doInBackground(Params) 后台执行 比较耗时的操作放在此处
onProgressUpdate(Progress) 显示进度
onPostExecute(Result) 任务执行完 调用的方法 任务执行的结果作为参数
接程序代码
新的页面 布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/text_display"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/hello_world" />
<Button
android:id="@+id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="点击开始倒计时"
/>
<TextView
android:gravity="center_horizontal"
android:id="@+id/text_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="当前时间" />
<TextView
android:id="@+id/tag_time"
android:gravity="center_horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="距离还有" />
<TextView
android:gravity="center_horizontal"
android:id="@+id/dao_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="24sp"
android:text="倒计时" />
</LinearLayout>
java代码
package com.example.theadtest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import android.R.integer;
import android.app.Activity;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.
4000
Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class NewPagerActivity extends Activity {
private TextView text_display, tag_time, text_time, dao_time;
private Button btn;
private Handler handler;
private static boolean state = false;
private static final String TIME_STRING = "2015-10-31-23-59-59";//把目标截止时间定义为常量,方便修改
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_pager);
text_time = (TextView) findViewById(R.id.text_time);
text_display = (TextView) findViewById(R.id.text_display);
dao_time = (TextView) findViewById(R.id.dao_time);
tag_time = (TextView) findViewById(R.id.tag_time);
btn = (Button) findViewById(R.id.btn);
tag_time.setText("距离" + TIME_STRING);
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
switch (msg.what) {
case 0:
String stime = msg.obj.toString();
text_time.setText(stime);
break;
case 1:
String s1 = msg.obj.toString();
if (Integer.parseInt(s1) <= 10) {
text_display.setTextColor(Color.CYAN);
text_display.setText(s1);
if (Integer.parseInt(s1) == 0) {
text_display.setText("Duang!!!!");
}
} else
text_display.setText(s1);
break;
default:
break;
}
}
};
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
new Mytime().start();
new Thread(new MyClick()).start();
// 开启异步任务
MyTask task = new MyTask();
task.execute();
}
});
}
class MyTask extends AsyncTask<Integer, Integer, Boolean> {
// 参数,对象类型1,启动的初始化数据 2,异步任务进度交互的数据 3,运行结果
/**
* @Override 即将启动的时候触发 一般用于准备工作
*/
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
dao_time.setText("-----开始!");// 纯属测试用的无意义
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.e("", "------------onPreExecute");
}
/**
* @Override
* 在异步任务运行个过程中 与UI交互的方法
*/
protected void onProgressUpdate(Integer... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
int timespan = values[0] / 1000;
long day = timespan / 86400;
long hour = timespan / 3600 - day * 24;
long min = timespan / 60 - hour * 60 - day * 24 * 60;
long sec = timespan % 60;
String txtString = "还有" + day + "天" + hour + "小时" + min + "分" + sec
+ "秒";
dao_time.setText(txtString);
}
/**
* @Override
* 惟一一个非UI线程运行的方法 主要处理异步任务
*/
protected Boolean doInBackground(Integer... params) {
int timespan = 0;
// 自定义时间格式
SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
// 根据定义state状态判定activity是否被销毁,否则可能,返回了,这个异步任务还在执行。
while (true && !state) {
try {
Thread.sleep(1000);
long endDate = s.parse(TIME_STRING).getTime();
long nowDate = System.currentTimeMillis();
timespan = (int) (endDate - nowDate);
if (timespan <= 0) {
return true;
}
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
publishProgress(timespan);
}
return true;
}
/**
* @Override 异步任务运行完毕后触发
*/
protected void onPostExecute(Boolean result) {
// TODO Auto-generated method stub
Log.e("", "------------onPostExecute");
if (result = true) {
dao_time.setText("活动倒计时结束");
Log.e("", "------------结束");
}
super.onPostExecute(result);
}
}
// Thread 使用 继承
class Mytime extends Thread {
public void run() {
while (true && !state) {
try {
Message msg = Message.obtain();
String s = new SimpleDateFormat("yyyy年-MM月-dd日-HH时-mm分-ss秒")
.format(System.currentTimeMillis());
msg.obj = "当前时间" + s;
msg.what = 0;
handler.sendMessage(msg);
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
// 实现接口
class MyClick implements Runnable {
public void run() {
try {
for (int i = 10; i >= 0; i--) {
Message msg = Message.obtain();
msg.obj = i;
msg.what = 1;
handler.sendMessage(msg);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* @Override
* activity销毁,改变state 异步里的doInBackground方法终止 返回true
*/
protected void onDestroy() {
// TODO Auto-generated method stub
state = true;
Log.e("", "------------onDestroy");
super.onDestroy();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.new_pager, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
截图如下,显示最后相加少了一秒,应该是,当前正在进行的那一秒!
相关文章推荐
- Python3写爬虫(四)多线程实现数据爬取
- C#实现多线程的同步方法实例分析
- ruby实现的一个异步文件下载HttpServer实例
- C#异步绑定数据实现方法
- Delphi实现毫秒级别的倒计时实例代码
- 浅谈chuck-lua中的多线程
- javascript 宝宝出生倒计时实现代码
- 科学知识:同步、异步、阻塞和非阻塞区别
- 探讨Ajax中同步与异步之间的区别
- C#简单多线程同步和优先权用法实例
- C#多线程学习之(四)使用线程池进行多线程的自动管理
- C#多线程编程中的锁系统(三)
- C#多线程学习之(六)互斥对象用法实例
- C#中异步回调函数用法实例
- 基于一个应用程序多线程误用的分析详解
- C#多线程学习之(三)生产者和消费者用法分析
- C#多线程学习之(一)多线程的相关概念分析
- C#多线程之Thread中Thread.IsAlive属性用法分析
- C#控制台下测试多线程的方法
- Ruby 多线程的潜力和弱点分析