Java线程与Android线程,Java多线程与android多线程

线程和进程的区别

线程和进程的素质:由CPU进行调剂的并发式执行任务,多个任务被快速轮换执行,使得宏观上具有多个线程或者进程同时执行的效果。

进程:在操作系统来说,一个运行的程序或者说一个动态的指令集合通常对应一个进程Process,它是系统进行资源分派和调剂的一个自力单位,也是拥有系统资源的基本单位。进程是系统中自力存在的实体,它可以拥有自己自力的资源,拥有自己私有的地址空间,进程之间不克不及直接拜候其他进程的地址空间。

线程:线程是CPU调剂的基本单位,也就是说在一个进程中可以有多个并发程序执行流,线程拓展了进程的概念,使得任务的执行获得更加的细分,所以Thread有时候也被称为Lightweight Process。线程是进程的执行单位,可是线程不是分派系统资源的单位,它们共享所在进程的资源,包含共享内存,公有数据,全局变量,进程文件描述符,进程措置器,进程代码段,进程用户ID等等。

线程自力拥有自己的线程ID,仓库,程序计数器,局部变量,寄存器组值,优先级,信号屏蔽码,毛病返回码等等,线程是自力运行的,其执行是抢占式的。线程共享进程资源,线程之间的通信要进程之间的通信来得容易很多。另外,线程的建立和销毁的开销也远远小于进程的系统开销。

一、start()与run()

1) start:

用start体例来启动线程,真正实现了多线程运行。通过挪用Thread类的start()体例来启动一个线程,这时无需期待run体例体代码执行完毕而直接继续执行下面的代码。这时此线程处于就绪(可运行)状态,并没有运行,一旦获得cpu时间片,就开始执行run()体例,这里体例 run()称为线程体,它包含了要执行的这个线程的内容,Run体例运行结束,此线程随即终止。

2) run:

run()体例只是类的一个普通体例罢了,如果直接挪用Run体例,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,这样就没有达到写线程的目的。总结:挪用start体例方可启动线程,把需要并行措置的代码放在run()体例中,start()体例启动线程将自动挪用 run()体例,这是由jvm的内存机制规定的。并且run()体例必须是public拜候权限,返回值类型为void.。

2、线程池

java.util.concurrent包主要介绍java中线程以及线程池的使用。在初始状态建立并维护一定命量的空闲线程,当有需要执行的任务,就交付给线程中的一个线程,任务执行结束后,该线程也不会死亡,而是回到线程池中重新变成空闲状态。用线程池控制线程数量,其他线程排队等待。一个任务执行完毕,再从队列的中取最前面的任务开始执行。若队列中没有期待进程,线程池的这一资源处于期待。当一个新任务需要运行时,如果线程池中有期待的工作线程,就可以开始运行了;不然进入期待队列。

为什么要用线程池:

1.减少了建立和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。

2.可以根据系统的承受能力,调剂线程池中工作线线程的数目,避免因为消耗过多的内存,而把办事器累趴下(每个线程需要年夜约1MB内存,线程开的越多,消耗的内存也就越年夜,最后死机)。

三、死锁

当线程需要同时持有多个锁时,有可能产生synchronized体例死锁。

规避死锁:

1、只在需要的最短时间内持有锁,考虑使用同步语句块取代整个同步体例;

2、尽量编写不在同一时刻需要持有多个锁的代码,如果不成避免,则确保线程持有第二个锁的时间尽量短暂;

3、建立和使用一个年夜锁来取代若干小锁,并把这个锁用于互斥,而不是用作单个对象的对象级别锁;

4个条件:

互斥条件:资源是独有的且排他使用,进程互斥使用资源,即任意时刻一个资源只能给一个进程使用,其他进程若申请一个资源,而该资源被另一进程占有时,则申请者期待直到资源被占有者释放。

不成剥夺条件:进程所获得的资源在未使用完毕之前,不被其他进程强行剥夺,而只能由获得该资源的进程资源释放。

请求和连结条件:进程每次申请它所需要的一部分资源,在申请新的资源的同时,继续占用已分派到的资源。

循环期待条件:在产生死锁时必定存在一个进程期待队列{P1,P2,…,Pn},其中P1期待P2占有的资源,P2期待P3占有的资源,…,Pn期待P1占有的资源,形成一个进程期待环路,环路中每一个进程所占有的资源同时被另一个申请,也就是前一个进程占有后一个进程所深情地资源。

四、ThreadLocal

ThreadLocal为每个使用该变量的线程提供自力的变量副本,所以每一个线程都可以自力地改变自己的副本,而不会影响其它线程所对应的副本.从线程的角度看,目标变量就象是线程的本地变量.ThreadLocal自身不会保存这些特定的数据资源,而是由每个线程自己来管理。每个Thread对象都有一个ThreadLocal.ThreadLocalMap类型的名为threadLocals的实例变量,它保存了ThreadLocal设置给这个线程的数据。当通过ThreadLocal的set(data)体例来设置数据的时候,ThreadLocal会首先获取当前线程的引用,然后通过该引用获取当前线程持有的threadLocals,最后,以当前ThreadLocal作为key,将要设置的数据设置到当前线程。

ThreadLocal接口支持泛型,只有4个体例:

void set(Object value)设置当前线程的线程局部变量的值。

public Object get()该体例返回当前线程所对应的线程局部变量。

public void remove()将当前线程局部变量的值删除,目的是为了减少内存的占用。当线程结束后,对应该线程的局部变量将自动被垃圾回收。

protected Object initialValue()返回该线程局部变量的初始值,该体例是一个protected的体例,显然是为了让子类笼盖而设计的。这个体例是一个延迟挪用体例,在线程第1次挪用get()或set(Object)时才执行,并且仅执行1次。ThreadLocal中的缺省实现直接返回一个null。

五、android多线程

为什么子线程中不允许对UI进行操作呢

因为Android的UI控件其实不是线程平安,多线程的并发拜候会带来UI控件的不成预期的状态,且考虑到加锁机制会带来性能上的问题,因此Android在设计早期就禁止子线程措置UI。UI操作时ViewRootImpl会对操作者所在的线程进行checkThread,如果非主线程,会抛出CalledFromWrongThreadException。

Android除java原生的Thread/Runnable等线程形态,还有哪些包装过了的有特点的线程形式?

AsyncTask: AsyncTask 封装了线程池和Handler,主要是为了便利开发者不去写自己的后台线程和界说Handler,而便利更新UI界面。

IntentService: IntentService从名字来看,可以知道它是一个办事,其内部采取HandlerThread执行任务,执行完毕后自动退出。其特点是它是Service,比起其他线程来说具有更高的优先级,不容易被系统杀死,而能够包管任务的执行。

HandlerThread: HandlerThread是一个具有消息循环loop的线程,也就是一开始就准备好了loop的线程,在其内部可以直接使用Handler。

HandlerThread

HandlerThread 是Thread的子类,它的特点是可以使用Handler的Thread。它的run体例体如下所示,外界可以通过handler来通知HandlerThread来措置某些事情,从这可以看出Handler的用处不但仅局限于措置UI相关的问题。public void run() { mTid = Process.myTid(); Looper.prepare(); synchronized(this) {  mLooper = Looper.myLooper();  notifyAll(); } Process.setThreadPriority(mPriority); onLooperPrepared(); Looper.loop(); mTid =-1;  }

IntentService IntentService封装了HandlerThread和Handler,可是它继承了Service,所以致使它的优先级比纯真线程要高,所以IntentService适合执行一些高优先级的后台任务。

ThreadPoolExecutor

public ThreadPoolExecutor(int corePoolSize,  int maximumPoolSize,  long keepAliveTime,  TimeUnit unit,  BlockingQueue workQueue,  ThreadFactory threadFactory,  RejectedExecutionHandler handler) {  this.corePoolSize = corePoolSize;  this.maximumPoolSize = maximumPoolSize;  this.workQueue = workQueue;  this.keepAliveTime = unit.toNanos(keepAliveTime);  this.threadFactory = threadFactory;  this.handler = handler; }

corePoolSize: 线程池的核心线程数,默认情况下, 核心线程会在线程池中一直存活, 即使处于闲置状态. 但如果将allowCoreThreadTimeOut设置为true的话, 那么核心线程也会有超时机制, 在keepAliveTime设置的时间过后, 核心线程也会被终止. maximumPoolSize: 最年夜的线程数, 包含核心线程, 也包含非核心线程, 在线程数达到这个值后,新来的任务将会被阻塞. keepAliveTime: 超时的时间, 闲置的非核心线程跨越这个时长,讲会被销毁回收, 当allowCoreThreadTimeOut为true时,这个值也作用于核心线程. unit:超时时间的时间单位. workQueue:线程池的任务队列, 通过execute体例提交的runnable对象会存储在这个队列中. threadFactory: 线程工厂, 为线程池提供建立新线程的功能. handler: 任务无法执行时,回调handler的rejectedExecution体例来通知挪用者.如果线程池中线程的数目少于corePoolSize,就算线程池中有其他的没事做的核心线程,线程池还是会重新建立一个核心线程;直到核心线程数目达到corePoolSize(常驻线程就位) 如果线程池中线程的数目年夜于或者等于corePoolSize,可是工作队列workQueue没有满,那么新的任务会放在队列workQueue中,依照FIFO的原则依次期待执行;(当有核心线程措置完任务空闲出来后,会检查这个工作队列然后取出任务默默执行去) 如果线程池中线程数目年夜于等于corePoolSize,并且工作队列workQueue满了,可是总线程数目小于maximumPoolSize,那么直接建立一个线程措置被添加的任务。 如果工作队列满了,并且线程池中线程的数目达到了最年夜数目maximumPoolSize,那么就会用最后一个构造参数handler措置;**默认的措置体例是直接丢失落任务,然后抛出一个异常。

Java多线程与android多线程-1.jpg (57.15 KB, 下载次数: 0)

2018-7-14 05:53 上传

更多内容回复查看:

游客,如果您要查看本帖隐藏内容请回复

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值