java线程详解(一)

1,相关概念简介

(1)进程:是一个正在执行的程序。每一个进程执行都有一个执行的顺序,该顺序就是一个执行路径,或者叫一个控制单元。用于分配空间。

(2)线程:就是进程中一个独立的控制单元,线程在控制着进程的执行,一个进程中至少有一个线程。

java虚拟机启动的时候会有一个进程java.exe,该进程中至少有一个线程在负责java程序的执行,这个线程运行的代码在main方法中,因此main方法是主线程。在更细节一点,java虚拟机不止一个线程,在启动main方法这个主线程时还有垃圾回收机制,其实这也是多线程。因此java虚拟机也是多线程。

2,线程的创建和启动

(1)继承Thread类创建线程

步骤:

(a)定义Thread类的子类。

(b)重写该Thread 类的run()方法。

(c) 创建一个线程对象。

(d)调用对象的start()方法启动进程,调用run()方法。

class Demo extends Thread   //(a)定义Thread类的子类。
{
    public void run(){   //(b)重写该Thread 类的run()方法。
        for(int i = 0; i < 100; i++){
            System.out.println(i + " demo run!");
        }

    }
    public static void main(String[] args)
    {
        Demo d = new Demo();  //(c) 创建一个线程对象。
        d.start();   //(d)调用对象的start()方法启动进程。
        //一下代码进行测试
        for(int i = 0; i < 100; i++){
            System.out.println(i + " main run!");
        }
    }
}

测试结果:

可以看出主线程和我们自定义的线程交替执行。

注意:

(a)创建的线程对象不能调用run()方法。如果调用run()方法就和平常的函数调用一样,达不到多线程执行的效果。调用start()方法,不仅开启线程,而且还调用了run()方法。

(b) 该程序多次运行的结果每次都不同,这是因为多个线程都在争夺cpu的执行权,每一个时刻只有一个线程在运行,cpu在做着快速切换,以达到看上去是同时运行的结果。这就是多线程的一个特点:随机性。谁抢到谁执行,执行多长时间是有cpu决定的。

(c)为什么要覆盖run()方法?Thead类用于描述线程,该类中的run方法只是存放要运行的代码的位置。

(d)其实Thread d = new Thread()可以创建一个线程的实例,但是d.start()却是开启Thread类的run()方法,该方法没有做任何定义。

(2)实现Runnable接口创建线程类

先看一个问题

//火车站有16张票,需要从四个窗口卖出,如果按照上面的多线程实现,程序如下
class Ticket extends Thread
{
    private int tick = 16;//票的张数---16
    public void run(){
        while(true){
            if(tick>0){
                //此处打印看是哪个窗口卖出的哪张票,这里简单的让票号从1  ---  16
                 System.out.println(Thread.currentThread().getName() + "...sale:" + tick--);
            }
        }

    }
    public static void main(String[] args)
    {
        Ticket t1 = new Ticket();
        Ticket t2 = new Ticket();
        Ticket t3 = new Ticket();
        Ticket t4 = new Ticket();

        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

结果我们可以看出不止卖了16张,其实每个窗口或者说线程都卖出16张票,这是不能忍受的。

有个方法:private int tick = 16;这句变为:private static int tick = 16。但一般不定义静态,因为它的生命周期太长。

正式进入第二种创建线程的方法:

//火车站有16张票,需要从四个窗口卖出,如果按照上面的多线程实现,程序如下
class Ticket implements Runnable
{
    private int tick = 16;//票的张数---16
    public void run(){
        while(true){
            if(tick>0){
                //此处打印看是哪个窗口卖出的哪张票,这里简单的让票号从1  ---  16
                 System.out.println(Thread.currentThread().getName() + "...sale:" + tick--);
            }
        }

    }
    public static void main(String[] args)
    {
        Ticket t = new Ticket();

        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);
        Thread t3 = new Thread(t);
        Thread t4 = new Thread(t);

        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

从这个结果我们可以看出达到了我们的目标。总结步骤:

(a)定义Runnable接口的实现类,并且重写该接口的run()方法。

(b)创建Runnable实现类的实例对象,并以此对象来作为Thread类的Target来创建Thread类对象。

Ticket t = new Ticket(); 该对象t并非是线程对象

Thread t1 = new Thread(t); 以对象t作为参数而创建的t1才是真正的线程对象

(c)调用该线程对象t1的方法start()来启动多线程。

可以在创建Thread对象时为该对象指定一个名字。

(3)常用方法

(a)返回对当前正在执行的线程对象的引用。

         public static Thread currentThread() 

(b)返回该线程对象的的名称。

public final String getName()

(4)注意事项

(a)继承Thread类的对象可以使用currentThread()方法,也可以使用this关键字。但是实现Runnable的实现类只能通过currentThread()方法获得当前对象。

(b)Runnable接口方式创建的多个线程可以共享线程类的实例的属性。所以非常适合多个相同的线程来处理同一份资源。(也就是为什么引出这种线程方式的卖票的那个例子)

(c)Runnable接口实现的方式下,还可继承其他的类。

3,线程的生命周期

新建:当程序使用new关键字创建一个线程对象时,该线程就处于新建状态,此时这个对象和其他java对象一样,仅仅有虚拟机为其分配内存,并初始化其初始值,此时的对象没有表现出线程的特征。

就绪:当新建的线程对象调用start()方法时(图中的1),该线程就处于就绪状态,虚拟机会为其创建方法调用栈和程序计数器,处于这个状态中的线程没有开始执行,只是表示可以执行了,至于什么时候执行,关键看虚拟机里面的调度器的调度。

运行:当就绪状态的现场获取了cpu的执行权(图中的2)开始执行run方法,则表示该线程处于运行状态。

阻塞:当线程开始运行时不可能一直处于运行状态,除非他的运行时间非常短,cpu还没有切换就已经运行结束,但这样的情况并不是大多数。一般情况下,cpu所分的时间片很多线程在这个时间内是完成不了的,此时线程运行就要中断,让其他线程获取执行机会。因此当一个运行中的线程发生如下情况时会进入阻塞状态。其实阻塞状态是一种运行中的线程的一种中断状态,此时不能运行,但是线程不能运行还有其他状态,比如说又恢复到就绪状态,下面就来说明。

(a)运行中的线程进入阻塞状态

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

(2)线程调用了一个阻塞式的IO方法,在方法在返回前线程被阻塞。

(3)线程在等待某个通知。

(4)线程试图获得一个同步监视器,但是该同步监视器被别的线程所持有。

(5)程序调用了线程的suspend方法将该线程挂起。这个方法容易导致死锁,已过时。

(b)运行中的线程进入就绪状态

(1)并非通过sleep()方法使得线程失去资源

(2)调用yield()方法就可以使得运行中的程序进入就绪状态。

(c)阻塞状态的线程进入就绪状态

(1)阻塞状态的线程只能进入就绪状态,不能直接进入运行状态

(2)调用sleep()方法经过了指定的时间

(3)线程调用的阻塞式IO方法已经返回

(4)线程成功的获得了某个等待的同步监视器

(5)线程在等待某个通知,而其他线程发出了一个通知

(6)处于被挂起的线程被调用了resume()方法。这个方法容易导致死锁,已过时。

死亡:线程结束就是死亡状态。

(1)正常结束线程

(2)线程抛出一个未捕获到的Exception或Error。

(3)使用该线程的stop()方法来终止线程。容易死锁,已过时。

注意:

(a)当新建一个线程对象时,线程处于新建状态,此时如果要是调用了该对象的run()方法,说明此时线程对象已经不是新建状态了,不能再来调用start()方法,只能对处于新建状态的线程对象调用start()方法。但是也不能对新建的线程对象调用两次start()方法。

(b)不要对一个已经死亡的线程调用start()方法。

(c)有一个方法可以检测该线程对象是否已经死亡。-----isAlive()方法,当线程处于新建和死亡状态,该方法返回false,反之!

时间: 2024-10-07 09:22:32

java线程详解(一)的相关文章

java 线程详解

5月7号  周末看了一下线程方面的内容 ,边看视频边看书还附带着参考了很多人的博客,一天的收获,写下来整理一下:感觉收获还是挺多的:过段时间可能看完java  这几大块要去看一下关于spring boot  的内容顺便  也整理一下:附上我参考的 几本书: 关于java  线程,首先要了解一下线程和进程之间的关系.区别以及他们之间的概念: 首先是线程: 什么是线程? 线程是在程序执行过程中能够执行部分代码的一个执行单元,也看看做是一个轻量级的进程:线程是程序内的程序控制流只能使用程序内分配给程序

java线程详解

Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程.比如在Windows系统中,一个运行的exe就是一个进程. 线程是指进程中的一个执行流程,一个进程中可以运行多个线程.比如java.exe进程中可以运行很多线程.线程总是属于某个进程,进程中的多个线程共享进程的内存. “同时”执行是人的感觉,在线程之间实际上轮换执行. 二.Jav

Java线程详解(三)

Java线程:新特征-有返回值的线程 在Java5之前,线程是没有返回值的,常常为了"有"返回值,破费周折,而且代码很不好写.或者干脆绕过这道坎,走别的路了. 现在Java终于有可返回值的任务(也可以叫做线程)了. 可返回值的任务必须实现Callable接口,类似的,无返回值的任务必须Runnable接口. 执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable任务返回的Object了. 下面是个很简单的例子: import jav

Java线程详解(二)

Java线程:新特征-线程池 线程池的基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理.当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源. 在使用线程池之前,必须知道如何去创建一个线程池,在Java5中,需要了解的是java.util.concurrent.Executors类的API,这个类提供大量创建连接池的静态方法,是必须掌握的. Java通过Executor

Java线程详解(一)

程序.进程.线程的概念  程序(program):是为完成特定任务.用某种语言编写的一组指令的集合.即指一段静态的代码,静态对象.  进程(process):是程序的一次执行过程,或是正在运行的一个程序.动态过程:有它自身的产生.存在和消亡的过程.     如:运行中的QQ,运行中的MP3播放器     程序是静态的,进程是动态的  线程(thread):进程可进一步细化为线程,是一个程序内部的一条执行路径.     若一个程序可同一时间执行多个线程,就是支持多线程的 Java中多线程的创建和使

java线程详解(三)

java线程间通信 首先看一段代码 class Res { String name; String sex; } class Input implements Runnable { private Res r; Input(Res r) { this.r = r; } public void run() { int x = 0; while(true){ if(x==0){ r.name = "mike"; r.sex = "male"; } else{ r.nam

Java线程详解----借鉴

Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程.比如在Windows系统中,一个运行的exe就是一个进程. 线程是指进程中的一个执行流程,一个进程中可以运行多个线程.比如java.exe进程中可以运行很多线程.线程总是属于某个进程,进程中的多个线程共享进程的内存. “同时”执行是人的感觉,在线程之间实际上轮换执行. 二.Jav

并发编程 || Java线程详解

通用线程模型 在很多研发当中,实际应用是基于一个理论再进行优化的.所以,在了解JVM规范中的Java线程的生命周期之前,我们可以先了解通用的线程生命周期,这有助于我们后续对JVM线程生命周期的理解. 首先,通用的线程生命周期有五种,分别是:新建状态(NEW).可运行状态(RUNNABLE).运行状态(RUN).休眠状态(SLEEP).终止状态(TERMINATED).生命流程如下图所示: 新建状态(NEW).线程在此状态,仅仅是在编程语言层面创建了此线程,而在真正的操作系统中是没有创建的.所以,

java线程详解(二)

1,线程安全 先看上一节程序,我们稍微改动一下: //线程安全演示 //火车站有16张票,需要从四个窗口卖出,如果按照上面的多线程实现,程序如下 class Ticket implements Runnable { private int tick = 16;//票的张数---16 public void run(){ while(true){ if(tick>0){ //这里的sleep(100)是这次程序要表的关键,只是个模拟而已 try{ Thread.sleep(100); }catch