您的位置:首页 > 移动开发 > Android开发

GeekBand第八周笔记

2016-07-03 15:54 615 查看
一、线程是什么

线程,有时被称为轻量级进程,是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针,寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。

一个线程可以创建和撤销另一个线程,同一进程的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。

线程也有就绪,阻塞和运行三种基本状态。

就绪状态就是指线程具备运行的所有条件,逻辑上可以运行,在等待处理机;

运行状态是指线程占有处理机正在运行;

阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行。每一个程序都 至少有一个线程,若程序只有一个线程,那就是程序本身。



线程属性

1.轻型实体

线程中的实体基本上不拥有系统资源,只是有一点必不可少,能保证独立运行的资源。

线程的实体包括:程序,数据, TCB。线程是动态概念,它的动态性由线程控制块TCB(Thread Control Block)

TCB包括: a,线程状态 b,当线程不运行时,被保存的现场资源 c,一组执行堆栈 d,存放每个线程的局部变量主存区

e, 访问同一个进程中的主存和其它资源。

用于指示被执行指令序列的程序计数器,保留局部变量,少数状态参数和返回地址等的一组寄存器和堆栈。

2、 独立调度和分派的基本单位

在多线程中OS,线程是能独立运行的基本单位,因而也是独立调度和分派的基本单位。由于线程很轻,故线程的切换非常迅速且开销小,在同一进程中。

3、可并发执行

在一个进程中的多个线程之间,可以并发执行,甚至允许一个进程中所有线程都能并发执行。同样,不同进程中的线程也能并发执行,充分利用和发挥了处理机与外围设备并行工作的能力。

4.共享进程资源

在同一进程中的各个线程,都可以共享该进程所拥有的资源,这表现:所有线程都具有相同的地址空间(进程的地址空间),这意味着,线程可以访问该地址空间的每一个虚地址。此外,还可以访问进程所拥有的已打开文件,定时器,信号量机等,由于同一个进程内线程共享内存和文件,所以线程之间互相通信不必调用内核。

二、多线程是什么?

多线程中,通常是一个进程中包括多个线程,每个线程都是作为利用CPU的基本单位,是花费最小开销的实体。

三、为什么要使用多线程?

效率更快,耗时操作不妨碍主线程进行其他任务,多项任务并行。

无论何时启动APP,所有的组件都会运行在一个单独的线程中(默认的)——叫做主线程。这个线程主要用于处理UI的操作并为视图组件和小部件分发事件等,因此主线程也被称作UI线程。

如果你在UI线程中运行一个耗时操作,那么UI就会被锁住,直到这个耗时操作结束。对于用户体验来说,这是非常糟糕的!这也就是为什么我们要理解Android上的多线程使用。

理解这些可以把一些复杂的工作移动到其它的线程中去执行。如果你在UI线程中运行一个耗时的任务,那么很有可能会发生ANR(应用无响应),这样用户就会很快地结束掉你的APP。

四、多线程的原理







五、Android中的多线程 。

 Android中的Main线程的事件处理不能太耗时,否则后续的事件无法在5秒内得到响应,就会弹出ANR对话框。所以就必须要使用多线程来处理耗时操作,避免出现卡顿和异常。

但是,Android是单线程模型,这意味着Android UI操作并不是线程安全的,所以UI操作必须在UI线程中执行。

所以如何沟通,就很重要。

当你新开线程去处理耗时任务,返回的结果如何在UI上更新:

在WorkerThread如何更新UI

Activity. runOnUIThread(Runnable);

View.post(Runnable)

View.postDelayed(Runnable)

Handler

代码如下:

//        UI线程
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.text_view);

new Thread(new Runnable() {
@Override
public void run() {
// 第一种 activity的方法
runOnUiThread(new Runnable() {
@Override
public void run() {
mTextView.setText("我在其他线程。。。。");
}
});
//  第二种
mTextView.post(new Runnable() {
@Override
public void run() {
mTextView.setText("我在其他线程。。。。");
}
});
//    第三种
mTextView.postDelayed(new Runnable() {
@Override
public void run() {
mTextView.setText("我在其他线程。。。。");
}
},1000);
//   第四种
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
mTextView.setText("我在其他线程。。。。");
}
});
}
});

}


多线程使用方法:

1.AsyncTask<>,异步处理适合一次性的任务。因使用次数较多,就不详述了。

2.Handler,灵活,但也不适合大数量任务。

private DownloadHandler mHandler=new DownloadHandler(this);

private void loadImagesByThread(final String url,final int id){
//通过Thread来new 出多个线程
new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
Log.e("当前线程:", ""+Thread.currentThread().getName());
Drawable drawable = null;
try {
drawable = Drawable.createFromStream(new URL(url).openStream(), "image.gif");
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Message msg = mHandler.obtainMessage();
msg.what = 2012;
msg.arg1 = id;
msg.obj = drawable;
msg.sendToTarget();

}

}).start();
}

public static class DownloadHandler extends Handler{
private WeakReference<MainActivity> mWeakReference;
public DownloadHandler(MainActivity activity) {
mWeakReference=new WeakReference<>(activity);
}

@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
MainActivity activity=mWeakReference.get();
switch (msg.what){
case 2012:
((ImageView)activity.findViewById(msg.arg1))
.setImageDrawable((Drawable)msg.obj);
break;
}
}
}


3、ExecutorServie线程池,适合处理大量线程。

通过Executors的静态方法来创建,一般有三种:

1.单线程 :Executors.newSingleThreadExecutor();

2.固定数量线程 :Executors.newFixedThreadPool();

3.动态线程 :Executors.newCachedThreadPool();

4.定时线程:Executors.newScheduleThreadPool();

这里我们用固定几个线程来应用,使用方法是创建ExecutorService对象,然后执行submit(r)可以发起一个Runnable对象。用线程池来管理的好处是,可以保证系统稳定运行,适用与有大量线程,高工作量的情景下使用,假如要展示1000张图片如果创建1000个线程去加载,保证系统会死掉。用线程池就可以避免这个问题,可以用几个线程轮流执行,几个一组,执行完的线程不直接回收而是等待下次执行,这样对系统的开销就可以减小不少。

private ExecutorService service = Executors.newFixedThreadPool(5);
private void loadImagesByExecutors(final String url,final int id){
service.submit(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
Log.e("当前线程程:",""+Thread.currentThread().getName());

try {
final Drawable drawable  = Drawable.createFromStream(new URL(url).openStream(), "image.gif");
mHandler.post(new Runnable(){
@Override
public void run() {//这将在主线程运行
// TODO Auto-generated method stub
((ImageView)MainActivity.this.findViewById(id)).setImageDrawable(drawable);
}
});

} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

});

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线程 android 多线程