Android多线程研究(1)——线程基础及源码剖析
来源:互联网 发布:php文件管理代码 编辑:程序博客网 时间:2024/05/02 04:35
从今天起我们来看一下Android中的多线程的知识,Android入门容易,但是要完成一个完善的产品却不容易,让我们从线程开始一步步深入Android内部。
一、线程基础回顾
package com.maso.test;public class TraditionalThread {public static void main(String[] args) {/* * 线程的第一种创建方式 */Thread thread1 = new Thread(){@Overridepublic void run() {try {sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}while(true){System.out.println(Thread.currentThread().getName());}}};thread1.start();/* *线程的第二种创建方式 */Thread thread2 = new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}while (true) {System.out.println(Thread.currentThread().getName());}}});thread2.start();/* * 线程的调用优先级 */new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}while(true){System.out.println("Runnable");}}}){public void run() {try {sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}while(true){System.out.println("Thread");}};}.start();}}上面代码中是我们都很熟悉的线程的两种创建方式,如果对这些还感到陌生请先看Java线程基础。
打开Thread类的源码可以看到Thread类有8个构造函数,我们先看看上面的两种构造函数的源码。
public Thread() { init(null, null, "Thread-" + nextThreadNum(), 0); }在构造的时候直接调用了init方法
private void init(ThreadGroup g, Runnable target, String name, long stackSize) { if (name == null) { throw new NullPointerException("name cannot be null"); } Thread parent = currentThread(); SecurityManager security = System.getSecurityManager(); if (g == null) { /* Determine if it's an applet or not */ /* If there is a security manager, ask the security manager what to do. */ if (security != null) { g = security.getThreadGroup(); } /* If the security doesn't have a strong opinion of the matter use the parent thread group. */ if (g == null) { g = parent.getThreadGroup(); } } /* checkAccess regardless of whether or not threadgroup is explicitly passed in. */ g.checkAccess(); /* * Do we have the required permissions? */ if (security != null) { if (isCCLOverridden(getClass())) { security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); } } g.addUnstarted(); this.group = g; this.daemon = parent.isDaemon(); this.priority = parent.getPriority(); this.name = name.toCharArray(); if (security == null || isCCLOverridden(parent.getClass())) this.contextClassLoader = parent.getContextClassLoader(); else this.contextClassLoader = parent.contextClassLoader; this.inheritedAccessControlContext = AccessController.getContext(); this.target = target; setPriority(priority); if (parent.inheritableThreadLocals != null) this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); /* Stash the specified stack size in case the VM cares */ this.stackSize = stackSize; /* Set thread ID */ tid = nextThreadID(); }里面的东西比较多,但是我们可以看到会初始化一个变量Runnable target;
下面我们再来看看run方法中是个什么东东?
@Override public void run() { if (target != null) { target.run(); } }原来run方法中会先判断是否初始化了Runnable target变量,如果没有则空实现,如果target不为空则先执行Runnable接口中的run方法。有的朋友可能会猜想下面的代码会先调用Runnable接口中的run方法,然后才调用Thread实现类中的run方法。
/* * 线程的调用优先级 */new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}while(true){System.out.println("Runnable");}}}){public void run() {try {sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}while(true){System.out.println("Thread");}};}.start();其实事实并非如此,因为上面代码中是一个匿名内部类,实际上是一种从Thread的继承和实现,所以下面的run方法覆盖了Thread中的run方法,所以Runnable中的run方法根本不会执行。
下面再看看Runnable接口的源代码
publicinterface Runnable { /** * When an object implementing interface <code>Runnable</code> is used * to create a thread, starting the thread causes the object's * <code>run</code> method to be called in that separately executing * thread. * <p> * The general contract of the method <code>run</code> is that it may * take any action whatsoever. * * @see java.lang.Thread#run() */ public abstract void run();}发现Runnable接口只有一个抽象的run方法。
为什么要搞一个Runnable接口来实现多线程呢?从Thread继承不是更方便吗?Runnable接口有如下优势,所以我们常常会选择实现Runnable接口:
1、适合多个程序代码的线程去处理同一个资源。
public class ThreadTest1 extends Thread {private int count = 5; public void run() { for (int i = 0; i < 7; i++) { if (count > 0) { System.out.println("count= " + count--); } } } public static void main(String[] args) { //这样实际上是创建了三个互不影响的线程实例 ThreadTest1 t1 = new ThreadTest1(); ThreadTest1 t2 = new ThreadTest1(); ThreadTest1 t3 = new ThreadTest1(); t1.start(); t2.start(); t3.start(); }}
public class ThreadTest1{ public static void main(String [] args) { MyThread my = new MyThread(); //开启了三个线程,但是操作的是同一个run方法 new Thread(my, "1号窗口").start(); new Thread(my, "2号窗口").start(); new Thread(my, "3号窗口").start(); } }class MyThread implements Runnable{ private int ticket = 5; //5张票 public void run() { for (int i=0; i<=20; i++) { if (this.ticket > 0) { System.out.println(Thread.currentThread().getName()+ "正在卖票"+this.ticket--); } } }}
2、避免Java特性中的单根继承的限制。
3、可以保持代码和数据的分离(创建线程数和数据无关)。
4、更能体现Java面向对象的设计特点。
11 0
- Android多线程研究(1)——线程基础及源码剖析
- Android多线程研究(3)——线程同步和互斥及死锁
- Android多线程研究(9)——线程锁Lock
- Android多线程研究(9)——线程锁Lock
- android 线程研究一(AsyncTask源码深度剖析)
- Android多线程研究(5)——线程之间共享数据
- Android多线程研究(7)——Java5中的线程并发库
- Android多线程研究(8)——Java5中Futrue获取线程返回结果
- 《线程》——多线程同步实例剖析
- Posix多线程编程(1)—线程基础
- Posix多线程编程(1)—线程基础
- java 多线程基础(一)——线程创建及五种状态
- 线程剖析(part2)—线程控制及线程属性
- redis源码剖析(基础数据结构篇)——ziplist
- C# 多线程研究1——线程同步(发牌模拟)
- 多线程-4-线程同步、线程安全问题及死锁研究
- Android 多线程及线程通信
- Android 多线程及线程通信
- sql server 2005中如何查询一个数据库中有多少张表?
- iOS数组排序方法
- MySQL优化原则
- android 位置服务 api
- Android学习笔记(十七)——使用意图调用内置应用程序
- Android多线程研究(1)——线程基础及源码剖析
- dbus-glib笔记
- 正则表达式--模式修正符
- word "程序发送命令时出现问题”。
- 操作系统引论
- android 多媒体(图像,视频,音频)api
- 数据库连接错误
- 孤儿院
- 接口程序:HTTP发送报文(PostMethod 发送)