内容简介:ActivityThread 为 Android 主线程ThreadLocal 存储器,做到只有该线程自己能够访问。就是多个线程访问同一份数据,每个线程得到数据不一致。理解为一个 Map,它的 set 和 get 方法都有一个“隐形的” key,那就是当前的线程对象,所以它才可以为每个线程保存一个数据副本。IntentService 继承自Service,并且是一个抽象类。IntentService封装了Handler和HandlerThread,所以这个Handler是子线程中的,适合执行耗时后台任务。
- 1.继承Thread
- 2.实现Runnable
- 3.Handler
- 4.AnsyTask
- 5.HandlerThread
ActivityThread 为 Android 主线程
2.AnsyTask
-
AsyncTask 最好在主线程中初始化。因为AsyncTask需要Handler来将执行结果回调切回主线程,Handler 中Looper.getMainLooper()。所以异步线程初始化也没关系
-
excute()最好在主线程中初始化。并且一个AsyncTask只能执行一次excute(),否则会报错。其内部有一个枚举类型的Status用于维护执行状态:PENDING、RUNNING、FINISHED。默认情况下是PENDING,表示可以执行,当调用execute方法之后,会检查其状态是否是PENDING,如果不是的话就会抛出异常。
-
经过测试。AsyncTask 可以在子线程初始化 和 excute() 可以在子线程中进执行
-
Android 1.6之前为串行,之后改为并行,3.0由改为串行。
-
execute()串行执行 —>调用executeOnExecutor(),并传入一个sDefaultExecutor(串行线程池)
-
sDefaultExecutor是SerialExecutor的一个实例,而且它是个静态变量。也就是说,一个进程里面所有AsyncTask对象都共享同一个SerialExecutor对象。
-
asyncTestThread.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,””); 并行执行最大5个线程。(固定线程数量的线程池)
AsyncTask.THREAD_POOL_EXECUTOR。也可以使用自己的线程池。
-
-
AsyncTask 中有两个线程池,SerialExecutor 和用于任务排队的线程池。
3.HandlerThread
- 继承自Thread,是一个子线程中创建了Handler
- HandlerThread 中run是无限循环,不需要时可以挂起,
- 在getLooper 中会try catch,避免looper为空
- 获取子线程创建Handler
//创建HandlerThread实例 HandlerThread mHandlerThread = new HandlerThread("handler_thread"); //开始运行线程 mHandlerThread.start(); //获取HandlerThread线程中的Looper实例 Looper loop = mHandlerThread.getLooper(); //创建Handler与该线程绑定。 mSubThreadHandler = new Handler(loop){ public void handleMessage(Message msg) {} }
4.ThreadLocal
ThreadLocal 存储器,做到只有该线程自己能够访问。就是多个线程访问同一份数据,每个线程得到数据不一致。理解为一个 Map,它的 set 和 get 方法都有一个“隐形的” key,那就是当前的线程对象,所以它才可以为每个线程保存一个数据副本。
5.IntentService
IntentService 继承自Service,并且是一个抽象类。IntentService封装了Handler和HandlerThread,所以这个Handler是子线程中的,适合执行耗时后台任务。
stopSelf(int startId) 会等任务执行结束后停掉服务,而stopSelf()会立即结束。
6.Handler
- 主线程创建
- Handler uiHandler = new Handler();
- Handler uiHandler = new Handler(Looper.getMainLooper());
- 创建子线程Handler
- Handler threadHandler = new Handler(mHandlerThread.getLooper());获取子线程Looper
- 原理,根据Looper找到关联的消息队列
子线程创建Handler,需要先进行 Looper.prepare()
new Thread(){ @Override public void run() { Looper.prepare(); //获取当前线程的Looper,并prepare(); Handler handler = new Handler() { @Override public void handleMessage(Message msg) { Toast.makeText(MainActivity.this, "handler msg", Toast.LENGTH_SHORT).show(); } }; handler.sendEmptyMessage(0); Looper.loop(); //looper开始处理消息。 } }.start();
7.继承Thread
TestThread testThread = new TestThread(); testThread.start(); class TestThread extends Thread { @Override public void run() { super.run(); } }
8.Runnable
TestRunnable run = new TestRunnable(); Thread tt = new Thread(run); tt.start(); class TestRunnable implements Runnable{ @Override public void run() { } }
9. AsyncTask 示例
AsyncTestThread asyncTestThread = new AsyncTestThread(); asyncTestThread.execute();// 串行 asyncTestThread.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");//并行 class AsyncTestThread extends AsyncTask<String, String, String> { // 1作用:执行 线程任务前的操作 @Override protected void onPreExecute() { Log.e("jfson", "pre 0"); super.onPreExecute(); } // 2作用:接收输入参数、执行任务中的耗时操作、返回 线程任务执行的结果 @Override protected String doInBackground(String... strings) { for (int i = 0; i < 100; i++) { try { Thread.sleep(100); //进度条每次更新10%,执行中创建新线程处理onProgressUpdate() publishProgress(String.valueOf(i)); } catch (InterruptedException e) { e.printStackTrace(); } } Log.e("jfson", "doInBackground finish :"); return "下载完成!"; } // 3作用:在主线程 显示线程任务执行的进度 @Override protected void onProgressUpdate(String... values) { Log.e("jfson", "onProgressUpdate :" + values[0]); super.onProgressUpdate(values); } // 4作用:接收线程任务执行结果..UI线程 @Override protected void onPostExecute(String s) { Log.e("jfson", "onPostExecute :" + s); super.onPostExecute(s); } // 5任务执行完成、UI线程 @Override protected void onCancelled() { Log.e("jfson", "onCancelled :"); super.onCancelled(); } }
10.多线程的实现 or api 实现
线程池API分析
- 1.创建
- a.ThreadPoolExecutor.newFixedThreadPool();创建线程数量固定的线程池
- b.ThreadPoolExecutor.newSingleThreadExecutor();线程数固定为1的线程池
- c.ThreadPoolExecutor.newCachedThreadPool();会缓存的线程池,线程数量可以从0到Integer.MAX_VALUE,超时时间为1分钟。线程池用起来的效果是:如果有空闲线程,会复用线程;如果没有空闲线程,会新建线程;如果线程空闲超过1分钟,将会被回收。
- d. ThreadPoolExecutor.newScheduledThreadPool();将会创建一个可定时执行任务的线程池。
- 2.BlockingQueue
- newCachedThreadPool的线程上限几乎等同于无限,但系统资源是有限的,任务的处理速度总有可能比不上任务的提交速度。因此,可以为ThreadPoolExecutor提供一个阻塞队列来保存因线程不足而等待的Runnable任务,这就是BlockingQueue。
- 3.SynchronousQueue
- newCachedThreadPool使用的SynchronousQueue十分有趣,看名称是个队列,但它却不能存储元素。要将一个任务放进队列,必须有另一个线程去接收这个任务,一个进就有一个出,队列不会存储任何东西。因此,SynchronousQueue是一种移交机制,不能算是队列。newCachedThreadPool生成的是一个没有上限的线程池,理论上提交多少任务都可以,使用SynchronousQueue作为等待队列正合适。
- 4.饱和策略
- 当有界的等待队列满了之后,就需要用到饱和策略去处理,ThreadPoolExecutor的饱和策略通过传入RejectedExecutionHandler来实现。如果没有为构造函数传入,将会使用默认的defaultHandler。
- a.AbortPolicy是默认的实现,直接抛出一个RejectedExecutionException异常,让调用者自己处理。
- b.DiscardPolicy的rejectedExecution直接是空方法,什么也不干。如果队列满了,后续的任务都抛弃掉。
- c.DiscardOldestPolicy会将等待队列里最旧的任务踢走,让新任务得以执行。
- d.CallerRunsPolicy,它既不抛弃新任务,也不抛弃旧任务,而是直接在当前线程运行这个任务。当前线程一般就是主线程啊,让主线程运行任务,说不定就阻塞了。如果不是想清楚了整套方案,还是少用这种策略为妙。
- 5.线程池的执行
- 线程池是由Worker类负责执行任务,Worker继承了AbstractQueuedSynchronizer,引出了 Java 并发框架的核心AQS。
- worker在线程池里的四种可能(Worker在构造函数里采用ThreadFactory创建Thread,在run方法里调用了runWorker,看来是真正执行任务的地方。)
- 6.线程池的关闭
- shutdown:不能再提交任务,已经提交的任务可继续运行;
- shutdownNow:不能再提交任务,已经提交但未执行的任务不能运行,在运行的任务可继续运行,但会被中断,返回已经提交但未执行的任务。
- 7.Join、wait、notify、notifyAll、run()和start()
- Join()将改线程优先级提升,执行完后才可以执行其他线程。底层是利用wait()实现,主线程先获得了t对象的锁,t执行完成后,主线程继续执行,其他线程开始执行。
- 在 Java 中,可以通过配合调用 Object 对象的 wait() 方法和 notify()方法或 notifyAll() 方法来实现线程间的通信。在线程中调用 wait() 方法,将阻塞等待其他线程的通知(其他线程调用 notify() 方法或 notifyAll() 方法),在线程中调用 notify() 方法或 notifyAll() 方法,将通知其他线程从 wait() 方法处返回。
- run()和start()
- 1) start()
用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行run()方法,这里方法 run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止。 - 2)run()方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到写线程的目的。总结:调用start方法方可启动线程,而run方法只是thread的一个普通方法调用,还是在主线程里执行。这两个方法应该都比较熟悉,把需要并行处理的代码放在run()方法中,start()方法启动线程将自动调用 run()方法,这是由jvm的内存机制规定的。并且run()方法必须是public访问权限,返回值类型为void。
- 1) start()
10.手写一个线程池
- 主要用 private BlockingQueue
taskQueue=new LinkedBlockingDeque (); 存储任务Runnable。 - //线程工作组,WorkerThread[] workThreads;存储初始化的线程
- taskQueue.take();// 获取并移除第一个元素 没有则扔进
public void execute(Runnable task) { synchronized (taskQueue) { taskQueue.add(task); taskQueue.notifyAll(); //当调用execute()方法的时候,执行notiry(),只会唤醒线程池中的一个线程,注意与notoryAll()的区别 } } /*内部类 即一个线程池对象*/ private class WorkThread extends Thread{ //该工作线程是否有效,用来接收该工作线程 private boolean isRunnable=true; /* * 关键所在,如果任务队列不空,则求出任务执行,若任务队列为空,则等待 */ @Override public void run() { //接收队列当中的任务对象 任务对象Runnable类型 Runnable r=null; while(isRunnable){ //队列同步机制 synchronized(taskQueue){ while(isRunnable && taskQueue.isEmpty()){//队列为空 try { taskQueue.wait(20); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(!taskQueue.isEmpty()){ try { r=taskQueue.take();// 获取并移除第一个元素 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(r!=null){ r.run();//执行任务 } executeTaskNumber++; r=null; } } } public void stopWorker(){ isRunnable=false; } }
HttpURLConnection
public static String get(IRequest request) { InputStream inputStream = null; HttpURLConnection httpURLConnection = null; try { URL url = new URL(buildGetUrl(request.getBaseUrl(), request.getParam(), request.getEncrypt())); openUrlConnection(url,httpURLConnection); normalSetting(httpURLConnection, Method.GET, request.getHeaders()); if (httpURLConnection == null) { return null; } int responseCode = httpURLConnection.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { inputStream = httpURLConnection.getInputStream(); String contentEncoding = httpURLConnection.getContentEncoding(); InputStream stream = null; try { stream = wrapStream(contentEncoding, inputStream); String data = convertStreamToString(stream); return data; } catch (IOException e) { return ""; } finally { closeQuietly(stream); } } return null; } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return ""; }
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。