16_Android的线程


目录

1.回顾Java当中的线程概念

2.MainThread与Worker Thread

3.Android当中的线程的使用 

值得注意的问题:


1.回顾Java当中的线程概念

提示:Java线程详细解析:点我查看

1.线程两种实现方式:

  • 实现线程方法一:定义一个线程类,它继承类 Thread 并复写其中的方法 run(),方法 run( ) 称为“线程体” (由于Java只支  持单继承,用这种方法定义的类不能再继承其他的类)。

注意:如果上面调用的不是 ft.start( )方法,而是执行ft.run( )就不是多线程,而是单线程运行,结果是:先执行 FirstThread ---->0  -100 然后再执行 main---->0 - 100。 

运行Text.java,两个线程无规律运行,谁抢占到CPU使用权,就是谁运行:

  •  实现线程方法二(常用):提供一个实现接口 Runnable 的类作为线程的目标对象,在初始化一个Thread类或者Thread子类的线程对象时,把目标对象传递给这个线程实例,由该目标 对象提供线程体。 

下面采用实例演示:

运行Text.java:

2.线程的声明周期

3.多线程同步

多个线程访问同一资源时,就会出现问题,可以使用同步代码块:  synchronized( this ) {    } 来进行线程同步。


2.MainThread与Worker Thread

MainThread为主线程,也称为为UI线程。其他都称为Worker Thread。

注意:在主线程之外,是不允许修改UI的属性,但是特殊的控件是可以的,比如:ProgressBar。


3.Android当中的线程的使用 

例子:

新建一个应用程序,命名为:S13_myThread1

在布局文件增加一个TextView控件,一个Button控件,一个ProgressBar控件。 代码如下:

<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/textViewId"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#00ff00"
        android:textSize="20dp"
        android:text="默认文字" />
    <ProgressBar 
        android:id="@+id/progressBarId"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/textViewId"
        style="?android:attr/progressBarStyleHorizontal"
        android:max="100"
        android:progress="0"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="20dp"/>
    <Button 
        android:id="@+id/buttonId"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="按钮"
        android:layout_below="@id/progressBarId"/>

</RelativeLayout>

 视图如下:

在MainActivity.java中新建一个线程,实现线程的方式和Java一样,使用上面方式1的方法实现:

然后声明引用,获取控件对象,为button绑定监听器,过程不赘述,详细点击:点我查看

代码如下:

package com.yuan.s13_mythread1;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

public class MainActivity extends Activity {

	private TextView textView;
	private Button button;
	private ProgressBar progressBar;
	//Main Thread
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //获取控件的对象
        textView =(TextView)findViewById(R.id.textViewId);
        button =(Button)findViewById(R.id.buttonId);
        progressBar=(ProgressBar)findViewById(R.id.progressBarId);
        //绑定监听器
        OnButtonListener listener = new OnButtonListener();
        button.setOnClickListener(listener);
    }
    class OnButtonListener implements OnClickListener{

		@Override
		public void onClick(View v) {
			Thread ft = new MyThread();
    		ft.start();
		}
    		
    }
    //Work Thread
    class MyThread extends Thread{

		@Override
		public void run() {
			try {
				Thread.sleep(1*1000); //休眠1s.
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			textView.setText("来自线程的修改");	
		}
    	
    }
    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;
    }
    
}

我们先分析上面的程序:在语法上面是没有错误的, 只要我们按钮一按下,就调用ft.start( )线程就开始运行,运行线程一开始就休眠1s,接着调用外部类textView变量的方法,修改TextView当中的内容,从语法上分析:(MyThread是一个MainActivity的内部类,使用了textView.setText("来自线程的修改");外部类外部类的成员变量和成员变量方法,本身是没有问题的)。

那我们试运行一下这个应用程序,发现竟然出错了,怎么回事:

再去看看错误信息,很明显不能再Work Thread 调用 Main Thread的TextView控件的属性,如果你需要去修改TextView属性的话就只能去主线程去修改(在主线程之外,原则上是不可以去修改UI的属性的):

 


但是有一些特殊的控件可以在 Work Thread中修改,比如ProgressBar控件,试试:

在MainActivity中的MyThread修改,其他不变,如下:

 运行程序:


像出现上面的问题,在Work Thread不能去访问UI,只有Main Tehread 能去访问,那全部只用Main Thread就可以吗?

答案肯定是不行的,我们通过一个例子演示:

如果我们不使用Work Thread ,至使用Main Thread,然后点击按钮之后,之间进去休眠状态10s,如果这样的话系统就会进入阻塞状态,看看会发生什么问题:

运行程序,出现ANR(Application no responding)错误,这就是线程阻塞:

注意:一个应用程序当中,主线程通常用于接收用户的输入,以及运算运算的结果返回给用户,所以主线程是不能阻塞,因为UI是放在主线程内的,用户点击界面,而主线程输入不能被接受到,就会产生ANR错误。

所以对与一些可能产生阻塞的操作,必须放在Worker Thread当中 。


值得注意的问题:

如果把对于一些可能产生阻塞的操作,放在Work Thread当中,虽然说不会让主线程处于完全堵塞的状态,那么你在Work Thread废了那么大的劲,把改获取的数据,该计算的数据计算完了,然后此刻你又不能在(Work Thread)去修改UI的属性,那样做补全都白搭了吗?

这样就引出了一种通讯机制:Handler机制,通过这种通信机制,work Thread 就可以把运算完的数据发送给主线程,然后再主线程去修改UI的属性,和用户进行交互,正是这种巧妙的设计,多线程才有了可能性。


 

附录: 

本博文Demo下载:https://github.com/zGuangYuan/Android- 

github的用法:点我查看

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值