多线程的杂烩

感谢作者无私奉献

http://www.cnblogs.com/sunddenly/p/4104180.html

多进程

  • 多任务操作系统可以通过周期性地将CPU从一个进程切换到另一个进程,来实现同时运行多个进程。 尽管对于一个CPU而言,它在某个时间点只能运行一个进程,但CPU可以在多个进程之间进行轮换执行,并且CPU的切换速度极高,使我们无法感知其切换的过程,就好像有多个进程在同时执行。
  • 进程是资源分配的最小单位,开辟新的进程也比较费资源。并发量不高

多线程

 归纳起采可以这样说:操作系统可以同时执行多个任务,每个任务就是进程;进程可以同时执行多个任务,每个任务就是线程。简而言之,一个程序运行后至少有一个进程,一个进程里可以包含多个线程,但至少要包含一个线程。

线程与进程不同:
1. 进程之间不能共享内存,但线程之间共享内存非常容易
2. 线程在程序中是独立的、并发的执行流,与分隔的进程相比,进程中线程之间的隔离程度要小。
3.  系统创建进程时需要为该进程重新分配系统资源,但创建线程则代价小得多,因此使用多线程来实现多任务并发比多进程的效率高
4. Java语言内置了多线程功能支持,而不是单纯地作为底层操作系统的调度方式,从而简化了Java的多线程编程

生命周期

https://www.cnblogs.com/sunddenly/p/4106562.html
特别之处:
将周期与jvm的东西结合。

线程间的状态转换:

当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态。在线程的生命周期中,它要经过新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)5种状态。尤其是当线程启动以后,它不可能一直”霸占”着CPU独自运行,所以CPU需要在多条线程之间切换,于是线程状态也会多次在运行、阻塞之间切换

线程周期中jvm的工作。
1. 新建状态,当程序使用new关键字创建了一个线程之后,该线程就处于新建状态,此时仅由JVM为其分配内存,并初始化其成员变量的值
2. 就绪状态,当线程对象调用了start()方法之后,该线程处于就绪状态。Java虚拟机会为其创建方法调用栈和程序计数器,处于这个状态中的线程并没有开始运行,只是表示该线程可以运行了。至于该线程何时开始运行,取决于JVM里线程调度器的调度
3. 运行状态,如果处于就绪状态的线程获得了CPU,开始执行run()方法的线程执行体,则该线程处于运行状态
4. 阻塞状态,当处于运行状态的线程失去所占用资源之后,便进入阻塞状态
5. 在线程的生命周期当中,线程的各种状态的转换过程
这里写图片描述

线程间的状态转换:

https://my.oschina.net/mingdongcheng/blog/139263
1. 新建(new):新创建了一个线程对象。

  1. 可运行(runnable):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权 。

  2. 运行(running):可运行状态(runnable)的线程获得了cpu 时间片(timeslice) ,执行程序代码。

  3. 阻塞(block):阻塞状态是指线程因为某种原因放弃了cpu 使用权,也即让出了cpu timeslice,暂时停止运行。直到线程进入可运行(runnable)状态,才有机会再次获得cpu timeslice 转到运行(running)状态。阻塞的情况分三种:

(一). 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。
(二). 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。
(三). 其他阻塞:运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。

  1. 死亡(dead):线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。
    这里写图片描述

线程调度

  • 抢占式调度策略
    • 系统会给每个可执行的线程一个小时间段来处理任务;当该时间段用完后,系统就会剥夺该线程所占用的资源,让其他线程获得执行的机会。在选择下一个线程时,系统会考虑线程的优先级
  • 协作式调度策略
    • 所有现代的桌面和服务器操作系统都采用抢占式调度策略,但一些小型设备如手机则可能采用协作式调度策略,在这样的系统中,只有当一个线程调用了它的sleep()或yield()方法后才会放弃所占用的资源——也就是必须由该线程主动放弃所占用的资源

线程控制

摘要
Java的线程支持提供了一些便捷的工具方法,通过这些便捷的工具方法可以很好地控制线程的执行

  1. join线程控制,让一个线程等待另一个线程完成的方法
  2. 后台线程(守护线程)Daemon Thread,又称为守护线程或精灵线程。它的任务是为其他的线程提供服务,如果所有的前台线程都死亡,后台线程会自动死亡
  3. 线程睡眠sleep,让当前正在执行的线程暂停一段时,并进入阻塞状态
  4. 线程让步yield,让当前正在执行的线程暂停,但它不会阻塞该线程,它只是将该线程转入就绪状态

总结:sleep 与yield区别

  1. sleep()方法暂停当前线程后,会给其他线程执行机会,不会理会其他线程的优先级;但yield()方法只会给优先级相同,或优先级更高的线程执行机会
  2. sleep()方法会将线程转入阻塞状态,直到经过阻塞时间才会转入就绪状态:而yield()不会将线程转入阻塞状态,它只是强制当前线程进入就绪状态。因此完全有可能某个线程调用yield()方法暂停之后,立即再次获得处理器资源被执行
  3. sleep()方法声明抛出了InterruptcdException异常,所以调用sleep()方法时要么捕捉该异常,要么显式声明抛出该异常;而yield()方法则没有声明抛出任何异常
  4. sleep()方法比yield()方法有更好的可移植性,通常不建议使用yield()方法来控制并发线程的执行

总结:sleep 与wait区别

  1. sleep 释放资源,但不释放锁;wait释放资源,又释放锁。
  2. sleep是Thread类的方法,wait是Object类中定义的方法
  3. sleep显式抛出异常,wait没有
  4. 释放完cpu资源后
    1. sleep方法的线程进入阻塞,等时间到后,进入可执行状态;
    2. wait/notify方法的线程必须放在同步代码块或者同步方法中。
      sychoronized(o){
      t1.wait();//t1线程被放到了对象o的一个队列中,t1线程进入阻塞等其他线程t2调用o.notify/notifyAll方法时,进入可执行状态;o.notify会从对象o的那个队列中随机一个线程赋予锁
      }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值