`
vipshichg
  • 浏览: 261625 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Java中的线程Thread总结

    博客分类:
  • java
阅读更多

 在Java中创建线程有两种方法:使用Thread类和使用Runnable接口。

  要注意的是Thread类也实现了Runnable接口,因此,从Thread类继承的类的实例也可以作为target传入这个构造方法。可通过这种方法实现多个线程的资源共享。
  线程的生命周期:
  1.新建状态(New):用new语句创建的线程对象处于新建状态,此时它和其它的java对象一样,仅仅在堆中被分配了内存
  2.就绪状态(Runnable):当一个线程创建了以后,其他的线程调用了它的start()方法,该线程就进入了就绪状态。处于这个状态的 线程位于可运行池中,等待获得CPU的使用权
  3.运行状态(Running): 处于这个状态的线程占用CPU,执行程序的代码
  4.阻塞状态(Blocked): 当线程处于阻塞状态时,java虚拟机不会给线程分配CPU,直到线程重新进入就绪状态,它才有机会转到 运行状态。
  阻塞状态分为三种情况:
  1)、 位于对象等待池中的阻塞状态:当线程运行时,如果执行了某个对象的wait()方法,java虚拟机就回把线程放到这个对象的等待池中
  2)、 位于对象锁中的阻塞状态,当线程处于运行状态时,试图获得某个对象的同步锁时,如果该对象的同步锁已经被其他的线程占用,JVM就会把这个线程放到这个对象的琐池中。
  3)、 其它的阻塞状态:当前线程执行了sleep()方法,或者调用了其它线程的join()方法,或者发出了I/O请求时,就会进入这个状态中。
  一、创建并运行线程
   当调用start方法后,线程开始执行run方法中的代码。线程进入运行状态。可以通过Thread类的isAlive方法来判断线程是否处于运行状 态。当线程处于运行状态时,isAlive返回true,当isAlive返回false时,可能线程处于等待状态,也可能处于停止状态。
  二、挂起和唤醒线程
   一但线程开始执行run方法,就会一直到这个run方法执行完成这个线程才退出。但在线程执行的过程中,可以通过两个方法使线程暂时停止执行。这两个方 法是suspend和sleep。在使用suspend挂起线程后,可以通过resume方法唤醒线程。而使用sleep使线程休眠后,只能在设定的时间 后使线程处于就绪状态(在线程休眠结束后,线程不一定会马上执行,只是进入了就绪状态,等待着系统进行调度)。
  虽然 suspend和resume可以很方便地使线程挂起和唤醒,但由于使用这两个方法可能会造成一些不可预料的事情发生,因此,这两个方法被标识为 deprecated(弃用)标记,这表明在以后的jdk版本中这两个方法可能被删除,所以尽量不要使用这两个方法来操作线程。
  三、终止线程的三种方法
  有三种方法可以使终止线程。
  1.  使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。
  2.  使用stop方法强行终止线程(线程中调用了阻塞代码)(这个方法不推荐使用,因为stop是依靠抛出异常来结束线程的,也可能发生不可预料的结果)。如果没有调用阻塞代码,可以正常结束线程。
  3.  使用interrupt方法中断线程(线程中调用了阻塞代码)(其实这种方法也是通过抛出异常来结束线程的)。如果没有调用阻塞代码,可以通过判断线程的中断标志位来介绍线程。
  线程的几个方法:
  join():等待此线程死亡后再继续,可使异步线程变为同步线程
  interrupt():中断线程,被中断线程会抛InterruptedException
  wait():等待获取锁:表示等待获取某个锁执行了该方法的线程释放对象的锁,JVM会把该线程放到对象的等待池中。该线程等待其它线程唤醒
  notify():执行该方法的线程唤醒在对象的等待池中等待的一个线程,JVM从对象的等待池中随机选择一个线程,把它转到对象的锁池中。使线程由阻塞队列进入就绪状态
  sleep():让当前正在执行的线程休眠,有一个用法可以代替yield函数——sleep(0)
  yield():暂停当前正在执行的线程对象,并执行其他线程。也就是交出CPU一段时间(其他同样的优先级或者更高优先级的线程可以获取到运行的机会)
 sleep和yield区别:
  1、sleep()方法会给其他线程运行的机会,而不考虑其他线程的优先级,因此会给较低线程一个运行的机会;yield()方法只会给相同优先级或者更高优先级的线程一个运行的机会。
  2、当线程执行了sleep(long millis)方法后,将转到阻塞状态,参数millis指定睡眠时间;当线程执行了yield()方法后,将转到就绪状态。
  3、sleep()方法声明抛出InterruptedException异常,而yield()方法没有声明抛出任何异常
  4、sleep()方法比yield()方法具有更好的移植性
  如果希望明确地让一个线程给另外一个线程运行的机会,可以采取以下的办法之一:
  1、调整各个线程的优先级
  2、让处于运行状态的线程调用Thread.sleep()方法
  3、让处于运行状态的线程调用Thread.yield()方法
  4、让处于运行状态的线程调用另一个线程的join()方法
  首先,wait()和notify(),notifyAll()是Object类的方法,sleep()和yield()是Thread类的方法。
  (1).常用的wait方法有wait()和wait(long timeout):
  void wait() 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。
  void wait(long timeout) 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待。
  wait()后,线程会释放掉它所占有的“锁标志”,从而使线程所在对象中的其它synchronized数据可被别的线程使用。
   wait()和notify()因为会对对象的“锁标志”进行操作,所以它们必须在synchronized函数或synchronized代码块中进 行调用。如果在non-    synchronized函数或non-synchronized代码块中进行调用,虽然能编译通过,但在运 行时会发生IllegalMonitorStateException的异常。
  (2).Thread.sleep(long millis),必须带有一个时间参数。
  sleep(long)使当前线程进入停滞状态,所以执行sleep()的线程在指定的时间内肯定不会被执行;
  sleep(long)可使优先级低的线程得到执行的机会,当然也可以让同优先级和高优先级的线程有执行的机会;
  sleep(long)是不会释放锁标志的。
  (3).yield()没有参数。
  sleep 方法使当前运行中的线程睡眼一段时间,进入不可运行状态,这段时间的长短是由程序设定的,yield 方法使当前线程让出CPU占有权,但让出的时间是不可设定的。yield()也不会释放锁标志。
  实际上,yield()方法对应了如下操作: 先检测当前是否有相同优先级的线程处于同可运行状态,如有,则把 CPU 的占有权交给此线程,否则继续运行原来的线程。所以yield()方法称为“退让”,它把运行机会让给了同等优先级的其他线程。
   sleep方法允许较低优先级的线程获得运行机会,但yield()方法执行时,当前线程仍处在可运行状态,所以不可能让出较低优先级的线程些时获得 CPU占有权。 在一个运行系统中,如果较高优先级的线程没有调用 sleep 方法,又没有受到 I/O阻塞,那么较低优先级线程只能等待所有较高优先级的线程运行结束,才有机会运行。
  yield()只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。所以yield()只能使同优先级的线程有执行的机会。
  volitile 语义
  volatile相当于synchronized的弱实现,也就是说volatile实现了类似synchronized的语义,却又没有锁机制。它确保对volatile字段的更新以可预见的方式告知其他的线程。
  volatile包含以下语义:
  (1)Java 存储模型不会对valatile指令的操作进行重排序:这个保证对volatile变量的操作时按照指令的出现顺序执行的。
   (2)volatile变量不会被缓存在寄存器中(只有拥有线程可见)或者其他对CPU不可见的地方,每次总是从主存中读取volatile变量的结 果。也就是说对于volatile变量的修改,其它线程总是可见的,并且不是使用自己线程栈内部的变量。也就是在happens-before法则中,对 一个valatile变量的写操作后,其后的任何读操作理解可见此写操作的结果。
  尽管volatile变量的特性不错,但是volatile并不能保证线程安全的,也就是说volatile字段的操作不是原子性的,volatile变量只能保证可见性(一个线程修改后其它线程能够理解看到此变化后的结果),要想保证原子性,目前为止只能加锁!
  数据同步:
  线程同步的特征:
   1、如果一个同步代码块和非同步代码块同时操作共享资源,仍然会造成对共享资源的竞争。因为当一个线程执行一个对象的同步代码块时,其他的线程仍然可以 执行对象的非同步代码块。(所谓的线程之间保持同步,是指不同的线程在执行同一个对象的同步代码块时,因为要获得对象的同步锁而互相牵制)
  2、每个对象都有唯一的同步锁
  3、在静态方法前面可以使用synchronized修饰符,但是要注意的是锁对象是类(用Object.class而不能用this),而不是这个类的对象。
  4、当一个线程开始执行同步代码块时,并不意味着必须以不间断的方式运行,进入同步代码块的线程可以执行Thread.sleep()或者执行Thread.yield()方法,此时它并不释放对象锁,只是把运行的机会让给其他的线程。
  5、synchronized声明不会被继承,如果一个用synchronized修饰的方法被子类覆盖,那么子类中这个方法不在保持同步,除非用synchronized修饰。
  6、synchronized 关键字能够修饰一个对象实例中的函数或者代码块。 在一个非静态方法中 this 关键字表示当前的实例对象。 在一个 synchronized 修饰的静态的方法中,这个方法所在的类使用 Class 作为实例对象
9
12
分享到:
评论
1 楼 845871400 2014-03-13  
[b][/b][/img]oran[url]  [/url]ge]

相关推荐

    Java 模拟线程并发

    Java 模拟线程并发 Java, 模拟线程并发,线程,并发 Java, 模拟线程并发,线程,并发 Java, 模拟线程并发,线程,并发 Java, 模拟线程并发,线程,并发

    线程 JAVA java线程 java线程第3版 java线程第2版第3版合集

    java线程第二版中英文 java线程第二版中英文 线程并不是新的概念:许多操作系统和语言都支持它们。在Java出现以前,似乎人人都在谈论线程,却很少有人使用它。用线程编程是技巧性很强的且不可移植。 而在Java中却...

    Java多线程机制(讲述java里面与多线程有关的函数)

    9.1 Java中的线程 9.2 Thread的子类创建线程 9.3 使用Runable接口 9.4 线程的常用方法 9.5 GUI线程 9.6 线程同步 9.7 在同步方法中使用wait()、notify 和notifyAll()方法 9.8 挂起、恢复和终止线程 9.9 计时器线程...

    java多线程thread实例

    java多线程thread实例,经过测试的,可以直接运行

    java多线程编程总结

    java多线程编程总结

    java 多线程设计模式 进程详解

    《Java线程 高清晰中文第二版》中文第二版(PDF) 前言 第一章 线程简介 Java术语 线程概述 为什么要使用线程? 总结 第二章 Java线程API 通过Thread类创建线程 使用Runable接口的线程 线程的生命周期 线程命名 ...

    Java多线程学习总结

    资源包含以下内容:  Java 线程及进程  Java 中的线程类(Thread)  Java 中的 Runnable 接口  两种实现多线程方式的对比分析  Java 中线程的同步

    JAVA多线程的总结

    JAVA 多线程总结 扩展java lang Thread类 实现java lang Runnable接口

    Thread实现多线程

    继承Thread类: 1必须重写run 方法:里面放置的实际的线程体 2 启动线程: 3创建Thread对象 4调用Thread对象的start 方法启动线程

    java多线程模拟队列实现排队叫号

    java多线程模拟队列实现排队叫号,多线程模拟排队叫号取号 java多线程模拟队列实现排队叫号,多线程模拟排队叫号取号

    Java多线程编程总结

    Java语言的多线程需要操作系统的支持。 Java 虚拟机允许应用程序并发地运行多个执行线程。Java语言提供了多线程编程的... 在Java中,多线程的实现有两种方式: 扩展java.lang.Thread类 实现java.lang.Runnable接口

    java多线程示例

    Java中的多线程有三种实现方式: 1.继承Thread类,重写run方法。Thread本质上也是一个实现了Runnable的实例,他代表一个线程的实例,并且启动线程的唯一方法就是通过Thread类的start方法。 2.实现Runnable接口,并...

    java 线程 dump 分析工具 2.3.3

    java 线程Dump 分析工具: Java的TDA线程转储分析器是一个用于分析Sun Java VM生成的线程转储和堆信息的小型Swing GUI(目前用1.4测试)。它从提供的日志文件中解析线程转储和类直方图。它提供关于发现的线程转储的...

    java_Thread.rar_java 多线程_java多线程

    Java多线程实例,是学习java多线程的好方法

    JAVA线程高级-线程按序交替执行

    java多线程按需交替执行,java新特性。

    java多线程设计模式详解(PDF及源码)

    书中包含Java线程的介绍导读、12个重要的线程设计模式和全书总结以及丰富的附录内容。第一章相关线程设计模式的介绍,都举一反三使读者学习更有效。最后附上练习问题,让读者可以温故而知新,能快速地吸收书中的...

    Java多线程实例代码

    6个非常经典的java多线程实例!欢迎下载!!!

    java多线程数据流发送信息

    java 多线程 数据流 tcp thread i/o

    java的多线程使用方法

    java多线程的使用方法如何使用,怎么使用,使用过程中有什么要注意的

Global site tag (gtag.js) - Google Analytics