`

java多线程基础

 
阅读更多

java多线程基础

转自:http://www.cnblogs.com/zrtqsk/p/3776328.html

一、线程

       线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。

二、线程状态

 

http://images.cnitblog.com/blog/497634/201312/18152411-a974ea82ebc04e72bd874c3921f8bfec.jpg

线程共包括以下5种状态。
1. 新建状态(New)         : 线程对象被创建后,就进入了新建状态。此时它和其他Java对象一样,仅仅由Java虚拟机分配了内存,并初始化其成员变量值。

2. 就绪状态(Runnable): 也被称为“可执行状态”。线程对象被调用了该对象的start()方法,该线程处于就绪状态。Java虚拟机会为其创建方法调用栈和程序计数器。处于就绪状态的线程,随时可能被CPU调度执行,取决于JVM中线程调度器的调度。

3. 运行状态(Running) : 线程获取CPU权限进行执行。需要注意的是,线程只能从就绪状态进入到运行状态。

4. 阻塞状态(Blocked)  : 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
    (01) 等待阻塞 -- 通过调用线程的wait()方法,让线程等待某工作的完成。
    (02) 同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态。
    (03) 其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

5. 死亡状态(Dead)    : 线程执行完了、因异常退出了run()方法或者直接调用该线程的stop()方法(容易导致死锁,现在已经不推荐使用),该线程结束生命周期。

三、wait()、notify()、nofityAll()方法 

在Object.java中,定义了wait(), notify()和notifyAll()等方法。

  wait()的作用是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的锁

  而 notify()和notifyAll()的作用,则是唤醒当前对象上的等待线程;notify()是唤醒单个线程,而notifyAll()是唤醒所有的线程。

Object类中关于等待/唤醒的API详细信息如下:
  notify()        -- 唤醒在此对象监视器上等待的单个线程,使其进入“就绪状态”。  
  notifyAll()   -- 唤醒在此对象监视器上等待的所有线程,使其进入“就绪状态”
  wait()                                     -- 让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法”,当前线程被唤醒(进入“就绪状态”)。
  wait(long timeout)                 -- 让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量”,当前线程被唤醒(进入“就绪状态”)。
  wait(long timeout, int nanos) -- 让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量”,当前线程被唤醒(进入“就绪状态”)。

 wait()的作用是让“当前线程”等待(会释放锁),而“当前线程”是指正在cpu上运行的线程!

 此处,http://www.cnblogs.com/skywang12345/p/3479224.html例子讲的非常详细。

 

四、yield()、sleep()、join()和interrupt()方法

1、yield() 

  yield()是Thread类的静态方法。它能让当前线程暂停,但不会阻塞该线程,而是由“运行状态”进入到“就绪状态”,从而让 其它具有相同优先级的等待线程获取执行权;但是,并不能保证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权;也有可能是 当前线程又进入到“运行状态”继续运行!

  值得注意的是,yield()方法不会释放锁

 

2、sleep()

  sleep()是Thread类的静态方法。该方法声明抛出了InterrupedException异常。所以使用时,要么捕捉,要么声明抛出。

  有2种重载方式:

——static void sleep(long millis)  :  让当前正在执行的线程暂停millis毫秒,并进入阻塞状态,该方法受到系统计时器和线程调度器的精度和准度的影响。

——static void sleep(long millis , int nanos)  :  让当前正在执行的线程暂停millis毫秒加nanos微秒,并进入阻塞状态,该方法受到系统计时器和线程调度器的精度和准度的影响。

  sleep() 的作用是让当前线程休眠,即当前线程会从“运行状态”进入到“休眠(阻塞)状态”。sleep()会指定休眠时间,线程休眠的时间会大于/等于该休眠时间;在线程重新被唤醒时,它会由“阻塞状态”变成“就绪状态”,从而等待cpu的调度执行。常用来暂停程序的运行。  

  同时注意,sleep()方法不会释放锁

 

3、join()

  join() 是Thread的一个实例方法。表示,当某个程序执行流中调用其他线程的join方法时,调用线程将被阻塞,直到被join的线程执行完毕。

有3种重载的形式:

——join()  :  等待被join的线程执行完成

——join(long millis)  :  等待被join的线程的时间最长为millis毫秒,若在millis毫秒内,被join的线程还未执行结束,则不等待。

——join(long millis , int nanos)  :  等待被join的线程的时间最长为millis毫秒加nanos微秒,若在此时间内,被join的线程还未执行结束,则不等待。

即当前线程内,用某个线程对象调用join()后,会使当前线程等待,直到该线程对象的线程运行完毕,原线程才会继续运行。

 

4、interrupt()   

  我们经常通过判断线程的中断标记来控制线程。 

      IO,syncronized 等不可被中断,即使调用了interrupte()也无效 

  interrupt()是Thread类的一个实例方法,用于中断本线程。这个方法被调用时,会立即将线程的中断标志设置为“true”。所以当中断处于“阻塞状态”的线程时,由于处于阻塞状态,中断标记会被设置为“false”,抛出一个 InterruptedException。所以我们在线程的循环外捕获这个异常,就可以退出线程了。

  interrupt()并不会中断处于“运行状态”的线程,它会把线程的“中断标记”设置为true,所以我们可以不断通过isInterrupted()来检测中断标记,从而在调用了interrupt()后终止线程,这也是通常我们对interrupt()的用法。

  Interrupted()是Thread类的一个静态方法,它返回一个布尔类型指明当前线程是否已经被中断,isInterrupted()是Thread类的实例方法,返回一个布尔类型来判断线程是否已经被中断。它们都能够用于检测对象的“中断标记”。区别是,interrupted()除了返回中断标记之外,它还会清除中断标记(即将中断标记设为false);而isInterrupted()仅仅返回中断标记。

五、Synchronized

1、原理

  在java中,每一个对象有且仅有一个同步锁。这也意味着,同步锁是依赖于对象而存在。

  当当前线程调用某对象的synchronized方法时,就获取了该对象的同步锁。例如,synchronized(obj),当前线程就获取了“obj这个对象”的同步锁。

  不同线程对同步锁的访问是互斥的。也就是说,某时间点,对象的同步锁只能被一个线程获取到!通过同步锁,我们就能在多线程中,实现对“对象/方法”的互斥访问。 例如,现在有个线程A和线程B,它们都会访问“对象obj的同步锁”。假设,在某一时刻,线程A获取到“obj的同步锁”并在执行一些操作;而此时,线程B也企图获取“obj的同步锁” —— 线程B会获取失败,它必须等待,直到线程A释放了“该对象的同步锁”之后线程B才能获取到“obj的同步锁”从而才可以运行。

 

2、基本规则

  第一条 :  当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程对“该对象”的该“synchronized方法”或者“synchronized代码块”的访问将被阻塞。
  第二条 :  当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程仍然可以访问“该对象”的非同步代码块
  第三条 :  当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程对“该对象”的其他的“synchronized方法”或者“synchronized代码块”的访问将被阻塞。

 

3、实例锁和全局锁

实例锁 -- 锁在某一个实例对象上。如果该类是单例,那么该锁也具有全局锁的概念。
               实例锁对应的就是synchronized关键字。
全局锁 -- 该锁针对的是类,无论实例多少个对象,那么线程都共享该锁。
               全局锁对应的就是static synchronized(或者是锁在该类的class或者classloader对象上)。

  就是说,一个非静态方法上的synchronized关键字,代表该方法依赖其所属对象。一个静态方法上synchronized关键字,代表该方法依赖这个类本身。

 

关于Java各种知识的总结,推荐大家一位博主skywang12345, 他的各种Java知识总结实在是详细易懂且经典,给了我不少帮助。

 参考:http://www.cnblogs.com/skywang12345/p/java_threads_category.html

 

  《疯狂Java讲义》

分享到:
评论

相关推荐

    JAVA多线程基础演练DEMO

    这个"JAVA多线程基础演练DEMO"提供了一些基础示例,帮助开发者更好地理解和掌握多线程的基本概念和用法。以下将详细讲解Java多线程的相关知识点: 1. **线程的创建** - **继承Thread类**:创建一个新类,继承自`...

    头歌java多线程基础介绍.doc

    头歌java多线程基础 “头歌”是一个在线教育平台,提供包括Java在内的多种编程语言的在线学习资源和课程。Java多线程基础是学习Java编程中非常重要的一部分,它涉及到如何同时运行多个任务,以充分利用现代多核...

    Java多线程干货系列(1)Java多线程基础编程开发技术

    Java多线程是Java编程中的重要...以上内容仅涵盖了Java多线程基础编程的一部分知识点,实际开发中还需要关注更多的并发控制策略、性能优化和调试技巧。对于深入理解Java多线程,还需要学习和实践更多相关的高级特性。

    java多线程基础资料

    Java多线程是Java编程中的一个...以上只是Java多线程基础知识的一部分,深入学习还包括线程池的配置与优化、线程安全的设计模式、并发工具类的使用等。理解和掌握这些知识点对于编写高效、稳定的多线程程序至关重要。

    java多线程基础说课PPT教案.pptx

    java多线程基础说课PPT教案.pptx

    java多线程基础篇讲解

    Java多线程基础篇讲解是针对初学者设计的教程,旨在用简洁明了的语言帮助学习者更容易理解多线程的概念和应用。多线程编程在现代计算机系统中扮演着重要角色,尤其在CPU主频发展遇到瓶颈的情况下,通过超线程技术和...

    java多线程基础知识

    Java多线程基础知识 Java多线程基础知识是Java编程语言中的一项重要技术,用于提高程序的执行效率和响应速度。在这里,我们将详细介绍Java多线程基础知识的相关概念和技术。 一、程序、进程和线程 程序(Program...

    Java多线程基础-01、数组概述.rar

    本资料“Java多线程基础-01、数组概述”将带你入门Java的多线程世界,并结合数组这一基本数据结构进行讲解。 首先,我们需要理解什么是线程。线程是操作系统分配CPU时间的基本单位,一个进程可以有多个线程,它们...

    java多线程基础学习文档

    以上就是Java多线程基础学习的一些关键知识点,理解并掌握这些内容对于进行高效的多线程编程至关重要。在实际开发中,还需要根据具体需求选择合适的线程模型和同步机制,以实现高效、安全的并发程序。

    Java 多线程基础笔记

    Java 多线程基础笔记

    头歌java多线程基础-Java多线程基础详解与实战指南

    内容概要:本文详细介绍了Java多线程的基础概念和关键技术点。首先解释了线程的基本概念、线程与进程的区别及其不同状态。接着,通过三种方式创建线程(继承Thread类、实现Runnable接口、使用Callable和Future接口)...

    Java多线程基础-03、数组定义方式二、元素默认值规则.rar

    总之,Java多线程基础是高效编程的关键,而理解数组定义和元素默认值规则则是构建安全、健壮的多线程程序的基础。通过合理运用多线程技术和掌握数组的内在特性,你可以编写出更加高性能、可扩展的Java应用程序。

    Java多线程基础-02、数组定义方式一、访问、注意事项.rar

    在Java编程语言中,多线程是程序设计中的一个重要概念,尤其在处理高并发和资源优化的场景下...通过观看"Java多线程基础-02、数组定义方式一、访问、注意事项.mp4"这个视频教程,你将能更深入地学习这些重要的知识点。

    头歌java多线程基础-day10.rar

    头歌java多线程基础-day10.rar

    头歌java多线程基础-day11.rar

    头歌java多线程基础-day11.rar

    头歌java多线程基础-day12.rar

    头歌java多线程基础-day12.rar

    java多线程基础说课学习课程.pptx

    java多线程基础说课学习课程.pptx

    java多线程基础说课学习教案.pptx

    java多线程基础说课学习教案.pptx

    java多线程基础说课PPT学习教案.pptx

    java多线程基础说课PPT学习教案.pptx

    java多线程设计

    一、Java多线程基础 1. 线程的创建:Java提供了两种创建线程的方式——继承Thread类和实现Runnable接口。继承Thread类可以直接创建一个新的线程类,而实现Runnable接口则可以将线程逻辑封装在任何类中,更利于代码...

Global site tag (gtag.js) - Google Analytics