进程享有内存空间,受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个多线程例子已完,好好消化吧。