【Android 初学者】简单理解:多线程

一个进程包括 多个线程
进程享有内存空间,受CPU控制,

1、多线程 快,虽然消耗资源,但是没有CPU这些分配,
像下载 这些消耗时间的动作,只能是线程!

2、多进程系统卡,程序容易奔溃。

3、线程切换 比 进程快!

内容:6个多线程例子:

1-3: 计数,

4,5: 模拟下载,

6:模拟信息发送和接收


先讲解两个:

  

这里例子一:很糟糕!

这是普通的,每次点击计数,它都是重新计算,

点击越多,数字之间的跳转越多

 

该说 是一个BUG呢?还是说,破程序!判断都没有


例子二:

这是一个优化过的,
1、无论点击多少次,只有一个计数!
2、有暂停计数 的功能
3、0-10后停止,要重新计数,然后从11开始计数!

 

功能板块:

  

温馨提示:
代码要在onCreate 外面写,
doStart 执行异步任务(多线程)
Handler 负责接收,发送消息。

构建过线程,最好要new Runnable


MainActivity.java 主页

package com.open_open.androidch10;

import android.app.Activity;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void testOne(View view){
Intent intent=new Intent(this,TestOneActivity.class);
startActivity(intent);
}
public void testTwo(View view){
Intent intent=new Intent(this,TestTwoActivity.class);
startActivity(intent);
}
}


activity_main.xml 主页布局

<?xml version="1.0" encoding="utf-8"?>
<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" >

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="多线程案例一"
android:onClick="testOne"
android:textSize="30sp"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="多线程案例二"
android:onClick="testTwo"
android:textSize="30sp"
/>

</LinearLayout>

一、多线程一,方法一

TestOneActivity.java 

package com.open_open.androidch10;

import android.app.Activity;
import android.os.Message;
import android.os.SystemClock;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import java.util.Timer;
import java.util.TimerTask;
import android.os.Handler;

public class TestOneActivity extends Activity {
private TextView showNumber;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_one);
showNumber=(TextView)findViewById(R.id.showNumber);
}

//执行异步任务
public void doStart(View view){
//构建一个Timer对象
Timer timer=new Timer();
//设置Timer任务,立刻执行
timer.schedule(new TimerTask() {
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
//构建一个消息
Message message=Message.obtain();
message.what=1;
message.obj=i;
//发送消息
handler.sendMessage(message);
SystemClock.sleep(1000);
}
}
}, 0,15*1000);
}

//构建一个Handler负责收发消息(收:重写HandleMessage)
private Handler handler=new Handler(){
public void handleMessage(Message msg) {
if(msg.what==1){
showNumber.setText(msg.obj.toString());
}
};
};
}


多线程一,页面布局一
activity_test_one.xml

<?xml version="1.0" encoding="utf-8"?>
<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/showNumber"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="25sp"
android:gravity="center"
android:text="0" />
<Button android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="开始计数"
android:onClick="doStart"/>

</LinearLayout>


二、多线程二,方法二

TestTwoActivity.java 

package com.open_open.androidch10;

import android.app.Activity;
import android.os.Message;
import android.os.SystemClock;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.os.Handler;

public class TestTwoActivity extends Activity {
private TextView showNumber;
private boolean isRun=true;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_two);
showNumber=(TextView)findViewById(R.id.showNumber);
}
Thread myThread;
public void doStart(View view){
if(myThread!=null && myThread.isAlive())
return;
isRun=true;
//构建一个多线程进行计数
myThread=new Thread(new Runnable() {
@Override
public void run() {
while (isRun){
int number= Integer.parseInt(showNumber.getText().toString());
number++;
if (number==10){
isRun=false;
}
//构建消息
Message message=Message.obtain();
message.what=1;
message.obj=number;
//发送消息
handler.sendMessage(message);
SystemClock.sleep(1000);
}
}
});
myThread.start();
}
private Handler handler=new Handler() {
public void handleMessage(Message msg){
if (msg.what==1){
showNumber.setText(msg.obj.toString());
}
};
};
public void doPause(View view){
isRun=false;
}
}


三、多线程二,页面布局二
activity_test_two.xml

<?xml version="1.0" encoding="utf-8"?>
<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/showNumber"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="25sp"
        android:gravity="center"
        android:text="0" />
    <Button android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="开始计数"
        android:onClick="doStart"/>
    <Button android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="暂停计数"
        android:onClick="doPause"/>
</LinearLayout>

-----------------------------------------------------------------------------------------------------------------------------------------------------
其他多线程例子:三 - 六 :计数,模拟下载2个,发送信息(这里可以解释抢红包 游戏)一个
----------------------------------------------------------------------------------------------------------------------------------------------------


三、多线程三:计数

还是一个计数,
1、点击开始,做出提示:开始计数!
2、如果你点了3次,就1-10后,又重新开始执行1-10,这样连续3遍!
3、没有重复或覆盖,只有按规律的执行次数


计数完毕!再点击,又重新开始

   



TestOneActivity.java

package com.open_open.androidch10_2;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import org.w3c.dom.Text;

public class TestOneActivity extends Activity {

    private TextView showNumber;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test_one);
        showNumber=(TextView)findViewById(R.id.showNumber);

    }

    //开始异步任务
    public void doStart(View view){
        new MyAsyncTask(this).execute(0);
    }

//Android中提供了一个AsyncTask【异步任务类】,提供了多线程支持

    class MyAsyncTask extends AsyncTask<Integer, Integer, Integer>{

        //定义一个Context
        private Context context;
        public MyAsyncTask(Context context){
            this.context=context;
        }

        //执行异步操作的方法,属于子线程[必须的]
        @Override
        protected Integer doInBackground(Integer... params) {
            for (int i = 1; i <= 10; i++) {
                //数据发生改变时,向主线程发送消息
                publishProgress(i);
                SystemClock.sleep(1000);
            }
            return 1;
        }

        //属于主线程,子线程启动前执行
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            Toast.makeText(context, "计数开始!", 3000).show();
        }

        //执行子线程过程中更新UI【属于主线程】
        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            showNumber.setText(values[0]+"");//更新UI
        }

        //从属于主线程, 子线程执行完毕后执行该方法
        @Override
        protected void onPostExecute(Integer result) {
            super.onPostExecute(result);
            if(result==1){
                Toast.makeText(context, "计数完毕!", 3000).show();
            }
        }

    }
}

activity_test_one.xml

<?xml version="1.0" encoding="utf-8"?>
<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/showNumber"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="30sp"
        android:text="0"
        android:gravity="center" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="开始计数"
        android:textSize="30sp"
        android:gravity="center"
        android:onClick="doStart"/>

</LinearLayout>


四、多线程四:模拟下载一:


  


TestTwoActivity.java

package com.open_open.androidch10_2;

import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.os.SystemClock;
import android.os.Bundle;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;

public class TestTwoActivity extends Activity {
    private ProgressBar prog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test_two);

        prog=(ProgressBar) findViewById(R.id.showProgress);
    }
//构建异步任务
    public void doDownLoad(View view){
        new MyAsyncTask(this).execute(0);
    }
    class MyAsyncTask extends AsyncTask<Integer,Integer,String>{
    //定义一个Context
        private Context context;
        public MyAsyncTask(Context context){
            this.context=context;
        }
    //执行异步操作的方法属于子线程
        protected String doInBackground(Integer... params){
            for (int i = 1; i <=100; i++) {
           //数据发生改变的时候,向主线程发送消息
                publishProgress(i);
                SystemClock.sleep(100);
            }
            return "success";
        }

//执行子线程过程中更新UI【属于主线程】
        protected void onProgressUpdate(Integer... values){
            super.onProgressUpdate(values);
            prog.setProgress(values[0]);
        }
//从属于主线程,子线程执行完毕后执行该方法
        protected void onPostExecute(String result){
            super.onPostExecute(result);
            if (result.equals("success")){
                Toast.makeText(context,"计数完毕!",3000).show();
            }
        }
    }

}


activity_test_two.xml

(progressBar :模拟的进度条)

<?xml version="1.0" encoding="utf-8"?>
<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">
    
    <ProgressBar
        android:id="@+id/showProgress"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="100"
        style="?android:attr/progressBarStyleHorizontal"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="下载"
        android:textSize="30sp"
        android:onClick="doDownLoad"/>

</LinearLayout>



五、模拟下载二:


看起来是不是比较逼真啊?



TestThreeActivity.java

package com.open_open.androidch10_2;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.AsyncTask;
import android.os.SystemClock;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

public class TestThreeActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test_three);
    }

    private MyAsyncTask task;
    public void doStart(View view){
        task=new MyAsyncTask(this);
        task.execute();
    }

    private ProgressDialog dialog;
    class MyAsyncTask extends AsyncTask<Void,Integer,String>{

        private Context context;
        public MyAsyncTask(Context context){
            this.context=context;
        }
        //执行多线程
        @Override
        protected String doInBackground(Void... params) {
            for (int i = 1; i <= 100; i++) {
                publishProgress(i);
                SystemClock.sleep(100);
            }
            return "success";
        }

        //执行多线程前执行动作
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            //打开一个进度条对话框
            dialog=new ProgressDialog(context);
            dialog.setTitle("下载");
            dialog.setMessage("文件正在下载中......");
            dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            dialog.setButton(ProgressDialog.BUTTON_NEGATIVE, "取消", new OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.dismiss();
                    task.cancel(true);
                }
            });
            dialog.show();
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            if(result.equals("success")){
                Toast.makeText(context, "下载完毕", 3000).show();
                dialog.dismiss();
            }
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            dialog.setProgress(values[0]);
        }

    }
}

activity_test_three.xml

<?xml version="1.0" encoding="utf-8"?>
<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">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="下载"
        android:onClick="doStart"
        android:textSize="30sp" />


</LinearLayout>


六、模拟信息的发送和接收:

例子(QQ红包:拼手气红包:发一个10块钱,分成10份,系统自动分为一个数组,

从0.01 -9.99,一共10分,你们抢到的红包,都是系统分好的数组数据而已,因为是多线程,一个接着一个

所以不存在大家抢到同一个红包,不存在抢票抢到同一张票)


   


TestFourActivity.java

package com.open_open.androidch10_2;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

public class TestFourActivity extends Activity {

    private TextView showText;
    private EditText sendText;

    private Handler currHandler, mainHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test_four);

        showText = (TextView) findViewById(R.id.showText);
        sendText = (EditText) findViewById(R.id.sendText);

        //构建一个主线程的Handler
        mainHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if (msg.what == 2) {
                    showText.setText(showText.getText().toString() + "\n" + msg.obj.toString());
                }
            }
        };
        //构建一个消息队列,接收其他人发布过来的消息
        new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();//消息队列准备完毕
                //子线程Handler,不能更新UI
                currHandler = new Handler() {
                    @Override
                    public void handleMessage(Message msg) {
                        super.handleMessage(msg);
//发消息给主线程
                        Message m = Message.obtain();
                        m.what = 2;
                        m.obj = msg.obj;
                        mainHandler.sendMessage(m);
                        SystemClock.sleep(200);
                    }
                };
                Looper.loop();//循环消息队列
            }
        }).start();
    }
    //发消息
    public void doSend(View view) {
        new Thread(new Runnable() {
            @Override
            public void run() {
//取到消息(取之互联网上推送过来的消息)
//String str=sendText.getText().toString();
//构建消息
                for (int i = 0; i < 5; i++) {
                    Message message = Message.obtain();
                    message.what = 1;
                    message.obj = "a:" + i;
//不断的向消息队列中发送消息
                    currHandler.sendMessage(message);
                }
            }
        }).start();
    }

    public void doExit(View view) {
        //关闭消息队列
        currHandler.getLooper().quit();
        this.finish();
    }

}


activity_test_four.xml

<?xml version="1.0" encoding="utf-8"?>
<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/showText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="30sp"
        android:text="没有消息" />
    <View
        android:layout_width="match_parent"
        android:layout_height="3dp"
        android:background="@android:color/holo_orange_light"
        />
    <EditText
        android:id="@+id/sendText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:lines="3"
        android:inputType="textMultiLine"
        android:hint="请输入消息" />
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="发送"
        android:onClick="doSend"
        android:textSize="28sp"/>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="退出"
        android:onClick="doExit"
        android:textSize="28sp"/>

</LinearLayout>


6个多线程例子已完,好好消化吧。




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值