全面解析JAVA多线程入门

    作者:课课家教育更新于: 2017-05-15 14:44:12

         今天,课课家就跟大家探讨一下java多线程入门,这方面的知识其实很简单的,只要你认真的阅读文章,我保证你一定可以学会JAVA多线程入门。有需要的小伙伴,可以参考一下。

    为什么使用多线程

      进程之间不能共享内存,但线程之间共享内存很容易

      系统创建进程需要为该进程重新分配系统资源,但创建线程代价小得多,因此使用多线程来实现多任务并发比多进程的效率高

      JAVA内置了多线程功能支持,而不是单纯的作为底层操作系统的调度方式,从而简化了JAVA的多线程编程

      线程的创建

    全面解析JAVA多线程入门_安全_操作系统_通信_课课家教育

      继承Thread类(可直接使用this关键字获得当前对象,多个线程无法共享线程类的实例变量)

      实现Runnable接口(必须使用Thread.currentThread()方法,多个线程可以共享线程类的实例变量)

      使用Callable和Future创建线程(call()方法作为线程执行体,可以有返回值去,可以声明抛出异常)

      线程的生命周期

    新建(New)--使用new关键词新建一个线程    就绪(Runnable)--调用start()方法    运行(Running)--处于就绪状态的线程获得CPU,开始执行run()方法体

      新建(New)--使用new关键词新建一个线程

      就绪(Runnable)--调用start()方法

      运行(Running)--处于就绪状态的线程获得CPU,开始执行run()方法体

      阻塞(Blocked)

      线程调用sleep()方法主动放弃所占用的处理器资源

      线程调用了一个阻塞式的IO方法

      线程试图获得一个同步监视器,但该监视器被其他线程所持有

      线程在等待某个通知

      程序调用了线程的suspend()方法将该线程挂起(容易导致死锁)

      死亡(Dead)

      run()方法或call()方法执行完成,线程正常结束

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

      直接调用该线程的stop()方法来结束该线程(容易导致死锁)

      控制线程

    join()方法--当某个程序执行流中调用其他程序的join()方法时,调用线程被阻塞,直到join()方法加入的join线程执行完为止

      join()方法--当某个程序执行流中调用其他程序的join()方法时,调用线程被阻塞,直到join()方法加入的join线程执行完为止

      setDemon()方法--将指定线程设置为守护线程

      sleep()方法--暂停线程的执行,并进入阻塞状态

      yield()方法--暂停线程的执行,并进入就绪状态

      setPriority()方法--改变线程的优先级,让优先级高的线程获得更多的执行机会

      Java线程具有五中基本状态

      新建状态(New):当线程对象对创建后,即进入了新建状态,如:Threadt=newMyThread();

      就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;

      运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;

      阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才有机会再次被CPU调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种:

      1.等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;

      2.同步阻塞--线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;

      3.其他阻塞--通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

      如果对什么是线程、什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内。

      用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现。说这个话其实只有一半对,因为反应“多角色”的程序代码,最起码每个角色要给他一个线程吧,否则连实际场景都无法模拟,当然也没法说能用单线程来实现:比如最常见的“生产者,消费者模型”。

      很多人都对其中的一些概念不够明确,如同步、并发等等,让我们先建立一个数据字典,以免产生误会。

      多线程:指的是这个程序(一个进程)运行时产生了不止一个线程

      并行与并发:

      并行:多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时。

      并发:通过cpu调度算法,让用户看上去同时执行,实际上从cpu操作层面不是真正的同时。并发往往在场景中有公用的资源,那么针对这个公用的资源往往产生瓶颈,我们会用TPS或者QPS来反应这个系统的处理能力。

      死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

      线程同步

      同步代码块(同步监视器为obj)

      synchronized(obj){...}

      同步方法(同步监视器为this)

      publicsynchronizedvoiddraw{}

      同步锁(Lock)

      //定义锁对象

      privatefinalReentrantLocklock=newReentrantLock();

      //加锁

      lock.lock();

      //释放锁

      lock.unlock();

      释放同步监视器的锁定

      当前线程的同步方法,同步代码块执行结束

      当前线程在同步方法,同步代码块遇到break,return终止了继续执行

      当前线程在同步方法,同步代码块出现未处理的异常

      当前线程执行同步方法,同步代码块时执行了同步监视器对象的wait()方法

      不释放同步监视器的情况

      线程执行同步方法,同步代码块时,程序调用Thread.sleep(),Thread.yield()方法来暂停当前线程的执行

      线程执行同步代码块时,其他线程调用了该线程的suspend()方法将该线程挂起

      线程通信

      传统的线程通信

      对于使用synchronized修饰的同步方法或代码块,借助Object类提供的wait(),notify(),notifyAll()方法

      使用Condition控制线程通信

      如果程序显式使用Lock对象保证同步,则使用Condition对象的await(),signal(),signalAll()来控制程序的协调运行

      使用阻塞队列(BlockingQueue)控制线程通信

      BlockingQueue接口:put()方法尝试把元素放入队列中,入托队列元素已满,则阻塞该线程,take()方法尝试从队列头部去取出元素,如果队列元素已空,则阻塞该线程

      线程池

    BlockingQueue接口:put()方法尝试把元素放入队列中,入托队列元素已满,则阻塞该线程,take()方法尝试从队列头部去取出元素,如果队列元素已空,则阻塞该线程

      Executors工厂类来产生线程池

      //返回ExecutorService对象的方法

      newCachedThreadPool()

      newFixedThreadPool(intnThreads)

      newSingleThreadExecutor()

      //返回ScheduleExecutorService线程池的方法

      newScheduledThreadPool(intcorePoolSize)

      newSingleThreadScheduledExecutor()

      //生成workstealing池,相当于后台线程池

      ExecutorServicenewWorkStealingPool(intparallelism)

      ExecutorServicenewWorkStealingPool()

      创建Runnable或者Callable实现类的实例

      调用ExecutorService对象的submit()方法来提交Runnable或者Callable实例

      调用ExecutorService对象的shutdown()方法关闭线程池

      ForkJoinPool--充分利用多核CPU

      创建ForkJoinPool实例

      创建有继承了返回值的RecursiveTask或无返回值的RecursiveAction实例

      调用ForkJoinPool的submit(ForkJoinTasktask)或submit(ForkJoinActionaction)方法来执行指定任务

      线程相关类

      ThreadLocal类

      隔离多个线程的数据共享,从根本上避免多个线程之间对共享资源的竞争

      包装线程不安全的集合类

      使用Collections提供的类方法包装

      线程安全的集合类

      以Concurrent开头的集合类

      以CopyOnWrite开头的集合类

         结束语:以上就是本篇文章的内容,看完文章的小伙伴都学会JAVA多线程入门了吧? 如果想更深的了解JAVA多线程,随时可以登陆课课家教育平台浏览,这里的知识内容全面,相信你一等会有不少的收获的。

课课家教育

未登录

1