zoukankan      html  css  js  c++  java
  • 多线程

    首先 了解下进程和线程的区别:

    进程:每个进程都有独立的代码空间和数据空间(进程上下文),进程间的切换会有很大的开销,一个进程包含1--n个线程

    线程:同一类线程共享一块代码和数据空间,每个线程有独立的程序计数器和方法调用栈(简称方法栈)

    在java中实现多线程的2中方法:继承Thread类、实现Runnable接口

    java线程的生命周期:

    当线程被启动过后,它既不是一启动就进入执行状态,也不是一直在执行状态,在java生命周期中,要经过新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)、死亡(Dead)五种状态;现在在创建以后,不可能一直霸占CUP独立运行,大部分时间处于运行和阻塞之间切换;

    一、新建和就绪状态:

    (1)用New关键字创建一个线程以后,该线程就进入了新建状态

    (2)调用start方法以后就进入就绪状态,但不能立刻进入运行状态,要等到JVM的线程调度器调度

    注意:只能对处于新建状态的线程调用start()方法,其他状态如果调用会报异常

    二、运行和阻塞状态

    (1)当处于就绪状态的线程获得cpu资源,jvm就会执行run方法,处于运行状态,当分配时间用完,又会进入就绪状态,等待下次分配cpu资源,

    (2)当遇到以下几种 情况会进入阻塞状态:

    <1>线程调用sleep()方法主动放弃cpu资源,

    <2>线程调用IO式的阻塞方法

    <3>等待某个通知wait

    <4>调用suspend方法挂起

    三、线程死亡

    (1)run方法执行完

    (2)线程抛出一个未捕获的异常

    (3)直接调用stop方法,但可能会导致死锁

    isAlive()方法判断该线程是否死亡(新建和死亡状态返回false)

     静态方法interrupted(),中断的状态由该方法清楚,第二次返回的是false

    Thread和Runnable的区别:

    如果一个类继承Thread,则不适合资源共享,如果一个类实现Runnable接口,则很容易实现资源共享

    main方法也是一个线程,在java中所有的线程都是同时启动的 ,至于什么时候,哪个先执行,完全看谁先得到cpu资源

    sleep()方法和wait()方法的区别:sleep是属于Thread类的,wait方法属于Object类的,调用后都会放弃cpu资源,进入阻塞状态,但是sleep()方法执行后线程不会丢锁,wait方法会丢锁,需要notify()方法唤醒

    Thread.yield()//线程让步,暂停当前正在执行的线程对象,把机会让给同等优先级或更高优先级的线程,当前线程回到可运行状态

    时不能保证这个线程不被再次选中(即无法保证达到让步的目的)。

    yield()从未导致线程转到等待/睡眠/阻塞状态。大多数情况下是从运行状态到可运行状态,有时可能没效果。

    sleep()和yield()的区别:

    <1>sleep()使得当前线程进入阻塞状态,该线程在指定的时间内肯定不会被执行,yield()只是回到可运行状态,一旦获取到资源就会被执行

    <2>sleep()方法被调用,释放cpu资源,允许较低优先级的线程获得机会,而yield()被调用时,只是让出cpu空间,进入可运行状态,

    让同等优先级的线程被执行,

    join()方法等待其他线程终止,在当前线程中调用另外一个线程的join()方法,则当前线程进入阻塞状态,直到另外一个线程结束,当前进程进入就绪状态 等待获取cpu资源,

    在很多情况下,主线程生成并启动子线程,如果子线程存在大量耗时间的运算,主线程往往先于子线程结束,但是如果主线程完成其他事务后需要子线程的处理结果,也就是主线程要等到子线程完成后再结束,这个时候就要用到join()方法了

    例如:在main方法里面创建2个线程后,start()全部启动,在分别调用这2个线程的join()方法,那么主线程(main)就会等待这2个线程完成后再结束,如果不加join方法,可能main主线程就会提前结束。

     线程调度器:线程调度器是一个后台操作系统服务,它负责为Runnable状态的线程分配Cpu时间,一旦我们创建一个线程并启动它,它便依赖于线程调度器的实现,时间分片是指分配给可用的Runnable线程的过程。分配cpu时间可以基于线程的优先级或者线程的等待时间,线程控制并不受到java虚拟机的控制,

    为什么sleep()和yield()方法是静态的?

    Thread的sleep()方法和yield() 方法都是指当前正在执行的线程上运行,所以处于其他等待状态的线程上调用这些方法时没有意义,并避免程序员错误的认为可以在其他非运行状态下调用这个方法

    如何确保线程安全:

    (1)同步

    (2)volatile关键字:当我们使用这个关键字修饰变量时,所有线程都只是读取这个变量但不缓存,这就确保线程读取的变量在同一内存中是一致的

    (3)使用原子类

    (4)实现并发锁

    (5)使用线程安全类

    线程池:对于并发的线程量很多,并且每个线程都是执行很短的时间就结束了,这样频繁的创建就会降低系统的效率,因为频繁的创建和销毁线程要消耗时间

    这时候就可以用线程池:

    ThreadPoolExecutor

  • 相关阅读:
    jQuery命名空间,自定义空间及属性,插件开发全解析 (转)
    打印输入表单中的内容
    js 网页烟花效果
    js学习cookie封装之获取
    js学习cookie封装之添加
    git基本使用
    最简单的手风琴效果
    js学习cookie封装之删除
    21个值得收藏的javas技巧
    javascript常用特效汇总
  • 原文地址:https://www.cnblogs.com/muliu/p/5505811.html
Copyright © 2011-2022 走看看