1.线程实现两种方式
- 继承Thread类,在run方法中执行操作
- 实现Runnable接口,在run方法中执行操作
2.多线程的创建
- 经典例子,售票(多个线程操作同一变量)
public class SaleTicket implements Runnable {
private int ticketNumber;
@Override
public void run() {
while (true){
synchronized (this){ //锁住这段代码,完成买票后,休眠200毫秒
if (ticketNumber>0){
Log.i("TAG",Thread.currentThread().getName()+"卖出了"+(20-ticketNumber+1)+"张票");
ticketNumber--;
}else {
break;
}
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
使用
public void testSale(){
SaleTicket saleTicket=new SaleTicket();
Thread t1=new Thread(saleTicket,"A代理");
Thread t2=new Thread(saleTicket,"B代理");
Thread t3=new Thread(saleTicket,"C代理");
Thread t4=new Thread(saleTicket,"D代理");
Thread t5=new Thread(saleTicket,"E代理");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
3.线程池的使用
- 缓存线程池
public void testCache(){
ExecutorService cacheThreadPool= Executors.newCachedThreadPool();
for (int i=0;i<10;i++){
int index=i;
try {
Thread.sleep(1000); //休眠后 被回收的线程再次拿出来用
} catch (InterruptedException e) {
e.printStackTrace();
}
cacheThreadPool.execute(new Runnable() {
@Override
public void run() {
Log.i("TAG",Thread.currentThread().getName()+" /// "+index); // 1 1 1
}
});
}
}
- 最长线程池
public void testFixed(){ //控制最大并发数
ExecutorService fixedThreadPool=Executors.newFixedThreadPool(3);
for (int i=0;i<10;i++){
int index=i;
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
Log.i("TAG",Thread.currentThread().getName()+" /// "+index); // 123 012 , 123 345, 123 678, 1 9
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
-
单一线程池
public void testSingle(){ ExecutorService singleThreadPool=Executors.newSingleThreadExecutor(); for (int i=0;i<10;i++){ int index=i; singleThreadPool.execute(new Runnable() { @Override public void run() { Log.i("TAG",Thread.currentThread().getName()+" /// "+index); } }); } }
- 定长线程池(支持定时及周期性任务执行)
public void testScheduled(){
Log.i("TAG","start schedule");
ScheduledExecutorService scheduledExecutorService=Executors.newSingleThreadScheduledExecutor();
// //定时三秒执行
// scheduledExecutorService.schedule(new Runnable() {
// @Override
// public void run() {
// Log.i("TAG","delay 3 seconds");
// }
// },3, TimeUnit.SECONDS);
//周期性执行 定时2秒以后执行,每隔3秒执行一次
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
Log.i("TAG","delay 2 seconds and excute 3 seconds" );
}
},2,3,TimeUnit.SECONDS);
scheduledExecutorService.shutdown(); //停止周期
}
###3.异步消息处理机制
- 线程与线程之间通讯 (在子线程中完成网络请求,需要改变UI界面,而UI只能在主线程中操作修改,故需要线程与线程间通讯)
- handler message messagequeue looper 间关系
![流程图](http://upload-images.jianshu.io/upload_images/1009095-8f5d35fccaaf3b46.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
简单消息发送接收实例:
private Handler handler=new Handler(){
//接收消息等待方
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//已回到主线程
switch (msg.what){
case 1:
btn.setText("按钮字样改变");
break;
case 2:
break;
}
}
};
public void testHandler(){
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000); //模拟网络请求耗时
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.sendEmptyMessage(1); //消息发送方
handler.sendEmptyMessageDelayed(2,2000); // 发送延迟2秒
}
}).start();
}
注: message 可携带少量信息内容 。
- post类方法允许排列一个runnable对象到主线程队列中,等待执行。那么也就可以更新UI了
public void testPostHandler(){
handler.post(new Runnable() {
@Override
public void run() {
Log.i("TAG"," post handler ");
}
});
new Thread(new Runnable() {
@Override
public void run() {
handler.postDelayed(new Runnable() {
@Override
public void run() {
btn.setText(" post类方法允许排列一个runnable对象到主线程队列中,等待执行。");
}
},2000);
}
}).start();
}
- 另一种在异步线程中更新UI的方式
runOnUiThread(new Runnable() {
@Override
public void run() {
}
});
###4.异步任务示例
public class DownloadTask extends AsyncTask
int progress;
//还在主线程中,可以做一些准备工作
@Override
protected void onPreExecute() {
super.onPreExecute();
Log.i("TAG","onPreExecute");
Log.i("TAG","准备下载");
//progressbar.setVisibility(View.VISIBLE);
}
//在异步线程执行 后台工作
@Override
protected Boolean doInBackground(Void... voids) {
Log.i("TAG","正在下载");
try {
while (true){
Thread.sleep(1000);
progress+=10;
//通知主线程我当前进度是多少
publishProgress(10);
publishProgress(progress);
if (progress>=100){
break;
}
}
} catch (InterruptedException e) {
return false;
}
return true;
}
//切换到主线程 请求完成后回调
@Override
protected void onPostExecute(Boolean s) {
super.onPostExecute(s);
//btn.setText(s);
if (s){
Log.i("TAG","下载成功");
//progressbar.setVisibility(View.GONE);
}else {
Log.i("TAG","下载失败");
}
}
//切换到主线程 更新UI 只有在doInBackground调用了publishProgress 才会调用此函数
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
// progressBar.setProgress(values[0]);
}
}