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

多线程篇之二JAVA多线程之概念篇

阅读更多

一:JAVA中的线程

    在java中线程的应用类主要在下面两个包中:

  • java.lang
  • java.util. concurrent

下图体现的是Java中最基础的线程类的关系拓扑图:

   

 

来看看java.lang.Runnable接口的源码:

 

package java.lang;
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

 

源码说明:

(1) Runnable中只有一个run()方法,且其类型是abstract()

(2) run()的解释:使用实现接口 Runnable 的对象创建一个线程时,启动该线程将导致在独立执行的线程中调用对象的 run 方法。 方法 run 的常规协定是,它可能执行任何所需的动作

 

Java.lang.Thread的源码:  

 

package thread;

package java.lang;

...

/**
 * 线程是程序中的执行线程,Java 虚拟机允许应用程序并发地运行多个执行线程。
 * 每个线程都有一个优先级,高优先级线程的执行优先于低优先级线程。每一个线
 * 程都可以或不可以标记为一个守护线程。当某个线程中运行的代码创建一个新
 * Thread对象时,该新线程的初始优先级被设定为创建线程的优先级,并且当且仅
 * 当创建线程是守护线程时,新线程才是守护线程。
 * 当JAVA虚拟机启动时,通常都会有单个非守护线程(它通常会调用某个指定类的
 * main方法)。Java 虚拟机会继续执行线程,直到下列任一情况出现时为止: 
 * 1:调用了Runtime类的exit()方法,并且安全管理器允许退出操作发生。
 * 2:所有的非守护线程都停止运行,无论是通过从对 run 方法的调用中返回,还
      是通过抛出一个传播到 run 方法之外的异常。
 */
public class Thread implements Runnable {
    /* 确保registerNatives是client(端)做的第一件事。 */
    private static native void registerNatives();
    static {
        registerNatives();
    }
    private char name[];
    private int priority;
    private Thread threadQ;
    private long eetop;
    /* 线程是否单步 */
    private boolean single_step;
    /* 线程是否是守护线程。 */
    private boolean daemon = false;
    /* JVM state */
    private boolean stillborn = false;
    /* 什么将被执行 */
    private Runnable target;
    /* 线程组 */
    private ThreadGroup group;
    /* 这个线程上下文类加载器 */
    private ClassLoader contextClassLoader;
    /* The inherited AccessControlContext of this thread */
    private AccessControlContext inheritedAccessControlContext;
    /* 用于自动编号的匿名线程 */
    private static int threadInitNumber;
    private static synchronized int nextThreadNum() {
        return threadInitNumber++;
    }
 
    /**线程的初始状态:not yet started/
    private volatile int threadStatus = 0;

    /**一个线程可以拥有的最低优先级为:1**/
    public final static int MIN_PRIORITY = 1;

    /**分配给一个线程的缺省优先级为: 5*/
    public final static int NORM_PRIORITY = 5;

    /**一个线程可以拥有的最高优先级为:10**/
    public final static int MAX_PRIORITY = 10;


    /**暂停当前正在执行的线程对象,并执行其他线程。**/
    public static native void yield();

    /**在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。*/
    public static native void sleep(long millis) throws InterruptedException;

    /**
     * 在指定的毫秒数加指定的纳秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。
     * 参数:millis 以毫秒为单位的休眠时间。
     *       nanos   要休眠的另外 0-999999 纳秒。 
     */
    public static void sleep(long millis, int nanos)throws InterruptedException { ... }

    /**初始化线程**/
    private void init(ThreadGroup g, Runnable target, String name,long stackSize) {}

    /** 分配新的 Thread 对象. **/
    public Thread() { init(null, null, "Thread-" + nextThreadNum(), 0);}

    /** 
	 * 分配新的 Thread 对象. 
	 * 参数:target - 任务 
	 */
    public Thread(Runnable target) { init(null, target, "Thread-" + nextThreadNum(), 0);}
  
    /** 
	 * 分配新的 Thread 对象. 
	 * 参数:name  - 新线程的名称
     *       target - 任务
     */
    public Thread(Runnable target, String name) { init(null, target, name, 0);}
    
    /** 
	 * 分配新的 Thread 对象. 
	 * 参数:name - 新线程的名称
     */
    public Thread(String name) { init(null, null, name, 0); }
	
	/** 
	 * 分配新的 Thread 对象. 
	 * 参数:group  - 线程组  
	 *       target - 任务	 
     * 异常:SecurityException - 如果当前线程无法在指定的线程组中创建线程
    public Thread(ThreadGroup group, Runnable target) {
        init(group, target, "Thread-" + nextThreadNum(), 0);
    }
	
    /** 
	 * 分配新的 Thread 对象. 
	 * 参数:name  - 新线程的名称
     *       group - 线程组
     * 异常:SecurityException - 如果当前线程无法在指定的线程组中创建线程
     */
    public Thread(ThreadGroup group, String name) {
        init(group, null, name, 0);
    }

    /** 
	 * 分配新的 Thread 对象. 
	 * 参数:name  - 新线程的名称
     *       target - 任务
	 *       group
     * 异常:SecurityException 如果当前线程不能在指定的线程组中创建线程或无法重写上下文类加载器的方法。         
     */
    public Thread(ThreadGroup group, Runnable target, String name) {
        init(group, target, name, 0);
    }

    /** 
	 * 分配新的Thread对象,以便将target作为其运行对象,将指定的name作为其名称,属于由组提到的线程组,并具有指定的堆栈大小。	 
	 * 参数:name  - 新线程的名称 target - 任务  group  - 线程组  stackSize - 栈大小
     * 异常:SecurityException 如果当前线程不能在指定的线程组中创建线程
     */
    public Thread(ThreadGroup group, Runnable target, String name,long stackSize) {
        init(group, target, name, stackSize);
    }

    /**
     * 使该线程开始执行; Java虚拟机调用该线程的run方法。
     * 其结果是两个线程同时运行,当前线程(该线程从调用start()方法返回)和另一个线程(该线程执行它的run()方法)。
     * 多次启动一个线程是无效的。 特别是当一个线程完成后,再被启动。
     * @exception  IllegalThreadStateException  如果线程已经启动
     */
    public synchronized void start() {...}

    private native void start0();

    /**
	 * 如果该线程使用了一个单独的Runnable进行对象构造,运行对象,则Runnable对象的run方法被调用。
	 * 否则,此方法不执行任何操作并返回。 
     */
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

    /**该方法被系统调用,主要是退出前进行清理工作**/
    private void exit() {
        if (group != null) {
            group.threadTerminated(this);
            group = null;
        }
        /* Aggressively null out all reference fields: see bug 4006245 */
        target = null;
        /* Speed the release of some of these resources */
        threadLocals = null;
        inheritableThreadLocals = null;
        inheritedAccessControlContext = null;
        blocker = null;
        uncaughtExceptionHandler = null;
    }

    
}

 

源码说明:

(1) 其实现了Runnable接口,而Runnable接口有一个run()方法,所以Thread也实现了该方法。

(2) 从其构造函数中的如下代码:

init(null, null, "Thread-" + nextThreadNum(), 0);

可以看出,线程名称创建的规则是:”Thread-”+创建的线程的个数(第几个线程) 

 

 

二:JAVA中线程的状态

1) New(新建)  新建的、至今尚未启动的线程处于这种状态。

 

2) Runnable(可运行状态): 包括就绪、运行中两个状态

     (1)Ready(就绪): 程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权 。

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

 

3) Wait/Blocked(暂停运行/阻塞): 

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

     (1). Timed Waiting:调用如下方法,线程处于暂停运行状态,直到等待时间已过,线程重新转入可运行(runnable)状态。

           

sleep(long timeout)
wait(long timeout)
wait(long timeout, int nanos)
join(long millis)
join(long millis, int nanos)
LockSupport.parkNanos(long nanos)
LockSupport.parkUntil(long deadline)

 

      (2). Waiting: 某一等待线程的线程状态。某一线程因为调用下列方法之一而处于等待状态,直到针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。

        

不带超时值的 Object.wait()
不带超时值的 Thread.join()
LockSupport.park()

 

      (3). Blocked:受阻塞并且正在等待监视器锁的某一线程的线程状态。处于受阻塞状态的某一线程正在等待监视器锁,以便进入一个同步的块/方法,或者在调用 Object.wait 之后再次进入同步的块/方法。

 

4) Terminated(终止):线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。



 

                              线程的生命周期图

 

 

三:线程的分类

Java线程可以分两类:

1.守护线程(daemon threads)

       守护线程通常为普通线程提供服务,它们通常有一个无限循环,等待服务请求或执行线程的任务,在没有其他的非守护线程运行时,守护线程将停止工作。即使你不创建任何线程,Java应用程序在默认情况下创建多个线程。他们大多是守护线程,主要用于处理任务,如垃圾收集或JMX。

   守护线程的特点:

  •  优先级非常低
  • 只有当同一个程序的任何其他线程正在运行时执行。
  • 当线程只剩下守护线程的时候,JVM就会退出.但是如果还有其他的任意一个用户线程还在,JVM就不会退出.

2.非守护线程 (non-daemon threads)或普通线程或用户线程(user threads)

用户线程和守护线程两者几乎没有区别,唯一的不同之处就在于虚拟机的离开:如果用户线程已经全部退出运行了,只剩下守护线程存在了,虚拟机也就退出了。 因为没有了被守护者,守护线程也就没有工作可做了,也就没有继续运行程序的必要了

 

在JAVA中通过调方法Thread.setDaemon(true)将线程转为守护线程。但需要注意的有:

1)但必须在调Thread.start()方法之前,因为一旦线程正在运行,你不能修改它的守护进程的状态。

2)在Daemon线程中产生的新线程也是Daemon的

3)守护线程应该永远不去访问固有资源,如文件、数据库,因为它会在任何时候甚至在一个操作的中间发生中断。

举例:

 

package thread;

public class DaemonTest {
    public static void main(String[] args) {
        new WorkerThread().start();
        try {
            Thread.sleep(7500);
        } catch (InterruptedException e) {}
        System.out.println("Main Thread ending") ;
    }

}
class WorkerThread extends Thread {

    public WorkerThread() {
    	System.out.println("线程是否为守护线程: "+this.isDaemon());
    	// When false, (i.e. when it's a user thread),
        // the Worker thread continues to run.
        // When true, (i.e. when it's a daemon thread),
        // the Worker thread terminates when the main 
        // thread terminates.
        setDaemon(true) ;   
        System.out.println("线程是否为守护线程: "+this.isDaemon());
    }

    public void run() {
        int count=0 ;
        while (true) {
            System.out.println("Hello from Worker "+count++) ;
            try {
                sleep(5000);
            } catch (InterruptedException e) {}
        }
    }
}

 

 

 

 

参考资料:

   http://blog.csdn.net/yyc1023/article/details/17428633

http://uule.iteye.com/blog/1100799

http://my.oschina.net/mingdongcheng/blog/139263

http://blog.csdn.net/yyc1023/article/details/17428633

http://www1.huachu.com.cn/read/readbookinfo.asp?sectionid=1000005042

http://lavasoft.blog.51cto.com/62575/99153

http://www.cnblogs.com/jinglingJuly/archive/2013/06/02/3113397.html

http://52android.blog.51cto.com/2554429/468031/

     http://www.uml-diagrams.org/examples/java-6-thread-state-machine-diagram-example.html

     http://www.cjsdn.net/doc/jdk50/java/lang/Thread.State.html

     http://architects.dzone.com/articles/how-analyze-java-thread-dumps

http://stackoverflow.com/questions/2213340/what-is-daemon-thread-in-java

 

 

 

 

  • 大小: 31.5 KB
  • 大小: 16.4 KB
0
1
分享到:
评论

相关推荐

    java多线程ppt

    java多线程PPT 多线程基本概念 创建线程的方式 线程的挂起与唤醒 多线程问题

    Java多线程编程实战指南(核心篇)

    Java多线程编程实战指南(核心篇) 高清pdf带目录 随着现代处理器的生产工艺从提升处理器主频频率转向多核化,即在一块芯片上集成多个处理器内核(Core),多核处理器(Multicore Processor)离我们越来越近了――如今...

    java多线程编程实战指南 核心篇 代码

    《Java多线程编程实战指南(核心篇)》以基本概念、原理与方法为主线,辅以丰富的实战案例和生活化实例,并从Java虚拟机、操作系统和硬件多个层次与角度出发,循序渐进、系统地介绍Java平台下的多线程编程核心技术及...

    java多线程编程总结

    详细的讲述了多线程的各种用法 Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调度-休眠...

    Java多线程编程总结

    Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调度-休眠 Java线程:线程的调度-...

    java多线程笔记

    Java线程:概念与原理 2 一、操作系统中线程和进程的概念 2 二、Java中的线程 3 三、Java中关于线程的名词解释 3 四、线程的状态转换和生命周期 4 Java线程:创建与启动 7 Java线程:线程名称的设定及获取 10 Java...

    Java多线程详解及示例

    本文将深入探讨Java多线程编程的重要性...介绍多线程概念,讨论多线程的优势,并提供实际示例。此外,还将探讨多线程编程中的常见问题以及如何避免这些问题。通过本文,您将获得对Java多线程编程的全面理解和实践经验。

    Java多线程编程技术

    《Java多线程编程核心技术》建议猿友们读两遍,因为其写得没有那么抽象,第一遍有些概念不是很理解,可以先跳过并记录起来,第一遍阅读的目的主要是了解整个架构。第二遍再慢慢品味,并贯穿全部是指点来思考,并将...

    Java多线程-多线程相关概念

    Java多线程--多线程相关概念

    Java多线程概念及应用详细解析

    Java多线程概念及应用详细解析.mht,I love java

    秒杀多线程第十六篇 多线程十大经典案例之一 双线程读写队列数据

    在《秒杀多线程系列》的前十五篇中介绍多线程的相关概念,多线程同步互斥问题《秒杀多线程第四篇一个经典的多线程同步问题》及解决多线程同步互斥的常用方法——关键段、事件、互斥量、信号量、读写锁。为了让大家...

    Java 多线程 PPT

    Java 进程与线程 线程的概念模型 线程类 线程的同步与互斥

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

    《JAVA多线程设计模式》PDF 下载 《Java线程 高清晰中文第二版》中文第二版(PDF) 前言 第一章 线程简介 Java术语 线程概述 为什么要使用线程? 总结 第二章 Java线程API 通过Thread类创建线程 使用Runable接口...

    Java多线程完全概念题

    自己整合的概念题,大概翻阅了十来篇多线程面试题,集合出来的概念题,可以参考参考

    JAVA 实验之多线程

    1. 掌握线程、多线程的概念和线程的生命周期; 2. 掌握创建单线程和多线程的方法,学会使用Thread类和实现Runnable接口。

    java多线程设计模式及源码

    多线程与并发处理是程序设计好坏优劣的重要课题,本书通过浅显易懂的文字与实例来介绍JAVA线程相关的设计模式概念,并且通过实际的JAVA程序范例和UML图示来一一解说,书中有代码的重要部分加上标注使读者更加容易...

    java多线程几个概念

    java多线程几个概念

Global site tag (gtag.js) - Google Analytics