Android 多线程,线程池

多线程特性:
原子性:同一时间只有一个操作,保证数据的正确性,所以需要synchronized或锁
可见性:一个线程对共享变量的修改,其它线程能够立即看到,所以需要volatile,场合单线程写,多线程读数据,只能修饰变量
顺序性:程序按照代码的先后顺序执行

synchronized保证原子性,可见性,可修饰方法,变量,类,可能造成线程的阻塞
volatile保证可见性,可修饰变量

Android多线程的方式:
1 Handler+Thread 多任务
2 AsyncTask 单任务
3 ThreadPoolExecutor 批处理任务
4 IntentService 处理异步任务的简单Service

线程池概念:
1 FixedThreadPool 定长线程池,固定数量不被回收,能快速响应外界请求,比如服务器端负载

// 1. 创建定长线程池对象 & 设置线程池线程数量固定为3
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
// 2. 创建好Runnable类线程对象 & 需执行的任务
Runnable task =new Runnable(){
  public void run(){
    System.out.println("执行任务啦");
     }
    };
// 3. 向线程池提交任务:execute()
fixedThreadPool.execute(task);
// 4. 关闭线程池
fixedThreadPool.shutdown();

2 SingleThreadPool 单线程线程池,所有任务只在一个线程中顺序执行

// 1. 创建单线程化线程池
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
// 2. 创建好Runnable类线程对象 & 需执行的任务
Runnable task =new Runnable(){
  public void run(){
        System.out.println("执行任务啦");
            }
    };
// 3. 向线程池提交任务:execute()
singleThreadExecutor.execute(task);
// 4. 关闭线程池
singleThreadExecutor.shutdown();

3 CachedThreadPool 可缓存线程池,无固定数量自动60s回收

// 1. 创建可缓存线程池对象
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
// 2. 创建好Runnable类线程对象 & 需执行的任务
Runnable task =new Runnable(){
  public void run(){
        System.out.println("执行任务啦");
            }
    };
// 3. 向线程池提交任务:execute()
cachedThreadPool.execute(task);
// 4. 关闭线程池
cachedThreadPool.shutdown();
//当执行第二个任务时第一个任务已经完成
//那么会复用执行第一个任务的线程,而不用每次新建线程。

4 ScheduledThreadPool 定时线程池,固定数量并周期执行

// 1. 创建 定时线程池对象 & 设置线程池线程数量固定为5
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
// 2. 创建好Runnable类线程对象 & 需执行的任务
Runnable task =new Runnable(){
       public void run(){
              System.out.println("执行任务啦");
          }
    };
// 3. 向线程池提交任务:schedule()
scheduledThreadPool.schedule(task, 1, TimeUnit.SECONDS); // 延迟1s后执行任务
scheduledThreadPool.scheduleAtFixedRate(task,10,1000,TimeUnit.MILLISECONDS);// 延迟10ms后、每隔1000ms执行任务
// 4. 关闭线程池
scheduledThreadPool.shutdown();

多线程实例:
0:Asyctask的使用

 button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new TessTwoTask().execute();
            }
        });

public class TessTwoTask extends AsyncTask<Void, Void, String> {
        @Override
        protected String doInBackground(Void... params) {
            bitmap = BitmapUtils.cutBitmap(BitmapUtils.getBitmapByAssets(getApplicationContext(), "i2.jpg"), mRect);
            baseApi.setImage(bitmap);
            return baseApi.getUTF8Text();
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            //background
            image.setBackground(new BitmapDrawable(bitmap));
            //info
            Log.i("result", result);
            textView.setText(result);
        }
    }
    

1:handler/thread,更新UI
//工作线程,在HandlerActivity doClick()方法中,获取数据后通过message发送数据Bitmap

new Thread() {
			public void run() {
				try {
					HttpEntity entity = service.getEntity("http://172.60.5.68:8080/time/1.jpg",
							null, HttpService.METHOD_GET);
					InputStream is = service.getStream(entity);
					Bitmap bm = BitmapFactory.decodeStream(is);
					
					// 发消息回主线程
					Message msg = Message.obtain();
					msg.obj = bm;
					handler.sendMessage(msg);
				} catch (ConnectTimeoutException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
			};
		}.start();

//主线程,在HandlerActivity onCreate()方法中,接收图片数据Bitmap并更新UI

service = new HttpService();
		handler = new Handler() {
			public void handleMessage(Message msg) {
				// 获取Bitmap
				Bitmap bm = (Bitmap) msg.obj;
				// 更新Imageview
				if (bm != null) {
					ivPic.setImageBitmap(bm);
				} else {
					ivPic.setImageResource(R.drawable.ic_launcher);
				}
			}
		};

2:handler/runnable,更新UI
//工作线程,在Handler_PostActivity中创建工作线程Runnable,完成耗时任务获取数据后runable直接更新UI

Runnable runnable = new Runnable() {
		public void run() {
			try {
				HttpEntity entity = service.getEntity("http://172.60.5.68:8080/time/1.jpg",
						null, HttpService.METHOD_POST);
				InputStream is = service.getStream(entity);
				final Bitmap bm = BitmapFactory.decodeStream(is);
				
				//直接更新UI
				if (bm != null) {
					ivPic.setImageBitmap(bm);
				} else {
					ivPic.setImageResource(R.drawable.ic_launcher);
				}
			} catch (ConnectTimeoutException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		};

//主线程:在Handler_PostActivity doClick()方法中发送post runnable

Handler handler = new Handler();  
	    handler.post(runnable);

3:handler/AsyncTask:
AsyncTaskActivity类中:
工作线程:

public static final String URI = "http://172.60.5.68:8080/time/1.jpg";
	class MyTask extends AsyncTask<String, String, Bitmap> {
		protected void onPreExecute() {
			iv.setImageResource(R.drawable.ic_launcher);
		}
		protected Bitmap doInBackground(String... params) {
			Bitmap bm = null;
			try {
				publishProgress("准备下载");
				HttpEntity entity = HttpUtils.getEntity(params[0], null,
						HttpUtils.METHOD_GET);
				InputStream is = HttpUtils.getStream(entity);
				bm = BitmapFactory.decodeStream(is);
			} catch (ConnectTimeoutException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			return bm;
		}
		protected void onProgressUpdate(String... values) {

		}
		protected void onPostExecute(Bitmap result) {
			if (result != null) {
				iv.setImageBitmap(result);
			} else {
				Toast.makeText(Day14_02_AsyncTaskActivity.this, "获取图片失败",
						Toast.LENGTH_LONG).show();
			}

		}
		protected void onCancelled() {
			super.onCancelled();
			cancel(true);
		}
	}

主线程:

public void doClick(View v) {
		MyTask task = new MyTask();
		task.execute(URI);
	}

4:handler.sendMessage(),更新UI
//工作线程,在StuDemoActivity setupView()方法中,获取数据后通过message发送数据students

new Thread() {
			public void run() {
				try {
					InputStream is = service.execute(HttpService.BASE_URL+ "stu_server/student", null, HttpUtils.METHOD_GET);
					ArrayList<Student> students = parser.parse(is, "utf-8");
					// 加载解析完成,发消息回主线程
					Message msg = Message.obtain();
					msg.what = 1;
					msg.obj = students;
					handler.sendMessage(msg);
				} catch (ConnectTimeoutException e) {
					e.printStackTrace();
					handler.sendEmptyMessage(0);
				} catch (Exception e) {
					e.printStackTrace();
				}
			};
		}.start();

//主线程,在StuDemoActivity onCreate()方法中,接收消息数据students并更新UI

this.handler = new Handler() {
			public void handleMessage(android.os.Message msg) {
				switch (msg.what) {
				case 1:// 更新listView
					ArrayList<Student> students = (ArrayList<Student>) msg.obj;
					adapter.changeData(students);
					break;
				case 0:// 连接超时
					Log.i("info", "连接超时异常提示。");
					Toast.makeText(Day11_04_StuDemoActivity.this, "网络连接超时",3000).show();

					break;
				}

			};
		};

5:handler.sendMessage(),耗时任务
//工作线程,在AsyncImageLoader AsyncImageLoader()构造方法中,获取数据后通过message发送数据ImageLoadTask

isLoop = true;
		tasks = new ArrayList<ImageLoadTask>();
		workThread = new Thread() {
			public void run() {
				Log.i("info", Thread.currentThread().getName() + " is started");
				while (isLoop) {
					while (tasks.size() > 0 && isLoop) {
						ImageLoadTask task = tasks.remove(0);
						try {
							byte[] data = service.getBytes(HttpService.BASE_URL
									+ task.path, null, HttpUtils.METHOD_GET);
							task.bitmap = BitmapUtils.getBitmap(data, 100, 100);
							// 发送消息回主线程
							Message msg = Message.obtain();
							msg.what = 0;
							msg.obj = task;
							handler.sendMessage(msg);
							// 缓存图片
							caches.put(task.path, new SoftReference<Bitmap>(task.bitmap));

							File savePath = new File("/mnt/sdcard/" + task.path);
							BitmapUtils.save(task.bitmap, savePath);
						} catch (ConnectTimeoutException e) {
							e.printStackTrace();
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
					if (isLoop == false)
						break;
					// 如果任务集合中的任务都执行完成,线程等待
					synchronized (this) {
						try {
							this.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
				Log.i("info", Thread.currentThread().getName()+ " is finished");
			};
		};
		workThread.start();
		
	class ImageLoadTask {
		private String path;
		private Bitmap bitmap;
		private Callback callback;
		public boolean equals(Object o) {
			ImageLoadTask task = (ImageLoadTask) o;
			return this.path.equals(task.path);
		}
		}
		
	public interface Callback {
		void imageLoaded(String path, Bitmap bm);
		}

//主线程,在AsyncImageLoader AsyncImageLoader()构造方法中,接收ImageLoadTask并加载

service = new HttpService();
		caches = new HashMap<String, SoftReference<Bitmap>>();
		handler = new Handler() {
			public void handleMessage(Message msg) {
				switch (msg.what) {
				case 0:// 图片加载成功
					ImageLoadTask task = (ImageLoadTask) msg.obj;
					task.callback.imageLoaded(task.path, task.bitmap);
					break;
				}
			}
		};

6:handler.sendMessage(),耗时任务
//工作线程----在MusicService(继承IntentService) onHandleIntent()方法中,该方法运行于工作线程,通过message发送savePath

String path = intent.getStringExtra("path");
		File savePath = new File("/mnt/sdcard/" + path);
		if (savePath.exists()) {
			Message msg = Message.obtain();
			msg.what = MSG_TAG_FILE_EXISTS;
			msg.obj = savePath;
			handler.sendMessage(msg);
			return;
		}
		try {// 连接服务端
			HttpEntity entity = HttpUtils.getEntity(
					HttpService.BASE_URL + path, null, HttpUtils.METHOD_GET);
			// 获取文件名和文件长度
			fileName = savePath.getName();
			fileLength = HttpUtils.getLength(entity);
			// 发送消息到主线程 ,开始下载
			handler.sendEmptyMessage(MSG_TAG_STARTED);
			// 下载
			InputStream is = HttpUtils.getStream(entity);
			StreamUtils.save(is, savePath, handler);
			// 发送消息到主线程 下载成功
			handler.sendEmptyMessage(MSG_TAG_SUCCESSED);
		} catch (ConnectTimeoutException e) {
			e.printStackTrace();
			handler.sendEmptyMessage(MSG_TAG_FAILED);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			handler.sendEmptyMessage(MSG_TAG_FAILED);
		} catch (IOException e) {
			e.printStackTrace();
			handler.sendEmptyMessage(MSG_TAG_FAILED);
		}

//主线程----在MusicService onCreate()方法中接收savePath并处理消息

handler = new Handler() {
			public void handleMessage(Message msg) {
				switch (msg.what) {
				case MSG_TAG_FILE_EXISTS:
					String info = "文件已存在,请勿重复下载:"+ ((File) msg.obj).getAbsolutePath();
					Toast.makeText(MusicService.this, info, 3000).show();
					break;
				case MSG_TAG_STARTED:// 开始下载,发通知到通知栏
					noti.contentView.setTextViewText(R.id.tvName_Noti, fileName);
					noti.contentView.setTextViewText(R.id.tvProgress_Noti,fileSizeFormat(0));
					noti.contentView.setTextViewText(R.id.tvTotalLength_Noti,fileSizeFormat(fileLength));
					noti.contentView.setProgressBar(R.id.pbDownload_Noti,(int) fileLength, 0, false);
					manager.notify(NOTI_ID, noti);
					break;
				case StreamUtils.MSG_TAG_CURRENT_PROGRESS:// 更新通知的下载进度
					int loadedLength = msg.arg1 * 1024;
					noti.contentView.setTextViewText(R.id.tvProgress_Noti,fileSizeFormat(loadedLength));
					noti.contentView.setProgressBar(R.id.pbDownload_Noti,(int) fileLength, loadedLength, false);
					manager.notify(NOTI_ID, noti);
					break;
				case MSG_TAG_FAILED:// 下载失败
					Notification noti1 = new Notification(android.R.drawable.ic_dialog_alert, "警告", System
									.currentTimeMillis());
					noti1.setLatestEventInfo(MusicService.this, "下载失败","音乐下载失败", contentIntent);
					noti1.flags = Notification.FLAG_AUTO_CANCEL;
					noti1.defaults = Notification.DEFAULT_LIGHTS;
					manager.notify(0, noti1);
					break;
				case MSG_TAG_SUCCESSED:// 下载成功
					manager.cancel(NOTI_ID);
				}

			}
		};

7:工作线程是独立一个类:

protected void updateUserSetting() {
		handler = null;
		handler = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				switch (msg.what) {
				case ConstantInfo.GET_DATA_OK01:
					user = (User) msg.obj;
					HuhangApplication.getHuhangApplication().setUser(user);
					break;
				case ConstantInfo.NET_WRONG:
					Toast.makeText(getBaseContext(), "网络异常 请检查您的网络",
							Toast.LENGTH_SHORT).show();
					break;
				case ConstantInfo.TOKEN_EXPRISSED:
					TokenExprissed exprissed = new TokenExprissed(
							FSPointActivity.this);
					exprissed.toLogin();
					break;
				default:
					break;
				}
				dismissPopuBar();
			}

		};

		new UpdateSettingThread(this, "0", settingValue + "", sp, handler)
				.start();
	}

8:获取验证码方法供调用:

private void GetCode() {
		getCodeHandler = new Handler() {
			public void handleMessage(Message msg) {

				switch (msg.what) {
				case GET_CODE_CODE_OK:
					if (mobileVerifyCodeBean.getReturnCode().equals("0")
							&& mobileVerifyCodeBean.getErrorCode().equals("0")) {

						Log.i("info", "服务器已发送验证码!");
						Toast.makeText(RegisterCheckMobileActivity.this,
								"验证短信已发送 请注意查收", Toast.LENGTH_SHORT).show();
						getCodeButton.setClickable(false);
						getCodeButton.setTextColor(getResources().getColor(
								R.color.lightGray));
						// 延时1分钟,才可再次获取验证码
						Timer timer = new Timer();
						timer.schedule(new TimerTask() {
							public void run() {
								getCodeHandler
										.sendEmptyMessage(BUTTON_CLICK_TRUE);
							}
						}, 1000 * 60);

						// 设置提示语可见
						// noteText.setVisibility(EditText.VISIBLE);
						Editor editor = sp.edit();
						editor.putString("accessToken",
								mobileVerifyCodeBean.getAccessToken());
						editor.putString("timestamp",
								mobileVerifyCodeBean.getTimestamp());
						editor.putString("mobileNumber",
								mobileVerifyCodeBean.getMobileNumber());
						editor.commit();

					} else if (mobileVerifyCodeBean.getReturnCode().equals("3")
							&& mobileVerifyCodeBean.getErrorCode().equals(
									"30123")) {

						editTextChange.changeToRed(registerMobileNumber);
						Toast.makeText(RegisterCheckMobileActivity.this,
								"该手机号已经被注册 请更换其他号码", Toast.LENGTH_SHORT).show();
						getCodeButton.setClickable(true);
						getCodeButton.setTextColor(getResources().getColor(
								R.color.darkGray));
						// nextButton.setClickable(false);
						// nextButton.setTextColor(android.R.color.darker_gray);
					}
					break;
				case BUTTON_CLICK_FALSE:
					getCodeButton.setClickable(false);
					getCodeButton.setTextColor(getResources().getColor(
							R.color.lightGray));
					break;
				case BUTTON_CLICK_TRUE:
					getCodeButton.setClickable(true);
					getCodeButton.setTextColor(getResources().getColor(
							R.color.darkGray));
					break;
				default:
					Toast.makeText(RegisterCheckMobileActivity.this,
							"网络连接异常,请连接您的网络!", Toast.LENGTH_SHORT).show();
					getCodeButton.setClickable(true);
					getCodeButton.setTextColor(getResources().getColor(
							R.color.darkGray));
					break;

				}
				dismissPopuBar();
			};
		};
		// 获取验证码的线程
		new Thread() {
			public void run() {
				getCodeHandler.sendEmptyMessage(BUTTON_CLICK_FALSE);
				// 发送请求,获取验证码
				if (netTool.checkNetIsAvailable()) {
					try {
						// 获取验证码的请求的返回信息
						getCodeResult = HttpConnectionManager
								.GetMoobileVerifyCode(mobileNumber, 1);
						Log.i("info", "获取验证码结果" + getCodeResult);
						// 创建一个验证码返回信息对象
						mobileVerifyCodeBean = gson.fromJson(getCodeResult,
								MobileVerifyCodeBean.class);
						if (mobileVerifyCodeBean != null) {
							// 向主线程发消息,获取验证码返回信息成功
							Message msg = new Message();
							msg.what = GET_CODE_CODE_OK;
							getCodeHandler.sendMessage(msg);
						}

					} catch (Exception e) {
						// 获取失败
						e.printStackTrace();
						getCodeHandler.sendEmptyMessage(0);
					}
				} else {
					// 获取失败
					getCodeHandler.sendEmptyMessage(0);
				}
			};
		}.start();
	}

9:保存用户数据工作线程方法:

private void SaveInfo() {
		titleRightButton.setClickable(false);
		final Handler saveHandler = new Handler() {
			public void handleMessage(android.os.Message msg) {
				dismissPopuBar();
				UserBean ub = (UserBean) msg.obj;
				switch (msg.what) {
				case SAVE_USER_INFO_OK:
					user = ub.getUser();
					HuhangApplication.getHuhangApplication().setUser(user);
					showUserInfo();
					updateInfo();
					
					Toast.makeText(UserInfoActivity.this, "保存成功",
							Toast.LENGTH_SHORT).show();
					
					break;
				case SAVE_USER_INFO_FAIL:
					Toast.makeText(UserInfoActivity.this, "保存信息失败",
							Toast.LENGTH_SHORT).show();
					break;
				case USER_NOT_FOUND:
					Toast.makeText(UserInfoActivity.this, "该账户已被注销",
							Toast.LENGTH_SHORT).show();
					break;
				case NET_WRONG:
					Toast.makeText(UserInfoActivity.this, "网络连接异常 请检查您的网络",
							Toast.LENGTH_SHORT).show();
					break;
				case ConstantInfo.TOKEN_EXPRISSED:
					TokenExprissed exprissed = new TokenExprissed(
							getApplicationContext());
					exprissed.toLogin();

				default:
					break;
				}
				titleRightButton.setClickable(true);
			};
		};
		new Thread() {
			String result = null;

			public void run() {
				List<NameValuePair> postParameters = new ArrayList<NameValuePair>();

				postParameters.add(new BasicNameValuePair("accessToken", sp
						.getString("accessToken", "")));
				postParameters.add(new BasicNameValuePair("timestamp", sp
						.getString("timestamp", "")));
				postParameters.add(new BasicNameValuePair("appId",
						ConstantUrl.APPID));
				postParameters.add(new BasicNameValuePair("accountId", sp
						.getString("accountId", "")));
				if (firstName.isShown()) {
					postParameters.add(new BasicNameValuePair("lastName",
							getTextValue(secondName)));
					postParameters.add(new BasicNameValuePair("firstName",
							getTextValue(firstName)));
				}
				postParameters.add(new BasicNameValuePair("email",
						getTextValue(email)));
				postParameters.add(new BasicNameValuePair("province",
						(province) + ""));
				postParameters.add(new BasicNameValuePair("address",
						toUTF8(getTextValue(address))));
				postParameters.add(new BasicNameValuePair("zipCode",
						getTextValue(zipCode)));
				postParameters.add(new BasicNameValuePair("homePhone",
						getTextValue(phone)));
				postParameters.add(new BasicNameValuePair("timeZone", timeZone
						+ ""));
				try {
					result = HttpConnectionManager.getDataFromHttp(
							ConstantUrl.UPDATE_USER_URL, postParameters);
					Log.i("info", "saveUserInfo:" + result);
				} catch (Exception e) {
					saveHandler.sendEmptyMessage(NET_WRONG);
					e.printStackTrace();
				}
				UserBean ub = gson.fromJson(result, UserBean.class);
				if (ub.getReturnCode().equals("0")
						&& ub.getErrorCode().equals("0")) {
					Message msg = new Message();
					msg.obj = ub;
					msg.what = SAVE_USER_INFO_OK;
					saveHandler.sendMessage(msg);
				} else if (ub.getReturnCode().equals("1")
						&& ub.getErrorCode().equals("10100")) {
					saveHandler.sendEmptyMessage(USER_NOT_FOUND);
				} else if (ub.getReturnCode().equals("3")
						&& ub.getErrorCode().equals("30303")) {
					saveHandler.sendEmptyMessage(ConstantInfo.TOKEN_EXPRISSED);
				} else {
					saveHandler.sendEmptyMessage(SAVE_USER_INFO_FAIL);
				}
			};
		}.start();
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值