java 多线程2:Thread的实例方法

Thread类中的方法调用方式:

学习Thread类中的方法是学习多线程的第一步。在学习多线程之前特别提出一点,调用Thread中的方法的时候,在线程类中,有两种方式,一定要理解这两种方式的区别:

1、this.XXX() 和 线程对象实例.XXX() 这里要首先参考 多线程 Thread.currentThread().getName() ,对象实例.getName() 和 this.getName()区别 理解采用Thread继承实现线程的几种启动方式出现的问题

这种调用方式表示的线程是线程实例本身

2、Thread.currentThread.XXX()或Thread.XXX() 这里一个是获取当前线程实例调用实例方法,一个是调用当前线程的静态的方法,都是指向当前调用方法的线程

上面两种写法是一样的意思。这种调用方式表示的线程是正在执行Thread.currentThread.XXX()所在代码块的线程

当然,这么说,肯定有人不理解两者之间的差别。没有关系,之后会讲清楚,尤其是在讲Thread构造函数这块。讲解后,再回过头来看上面2点,会加深理解。

Thread类中的实例方法

从Thread类中的实例方法和类方法的角度讲解Thread中的方法,这种区分的角度也有助于理解多线程中的方法。实例方法,只和实例线程(也就是new出来的线程)本身挂钩,和当前运行的是哪个线程无关。看下Thread类中的实例方法:

1、start()

start()方法的作用讲得直白点就是通知"线程规划器",此线程可以运行了,正在等待CPU调用线程对象得run()方法,产生一个异步执行的效果。通过start()方法产生得到结论,先看下代码:

public class MyThread02 extends Thread
{
    public void run()
    {
        try
        {
            for (int i = 0; i < 3; i++)
            {
                Thread.sleep((int)(Math.random() * 1000));
                System.out.println("run = " + Thread.currentThread().getName());
            }
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }
}
public static void main(String[] args)
{
    MyThread02 mt = new MyThread02();
    mt.start();

    try
    {
        for (int i = 0; i < 3; i++)
        {
            Thread.sleep((int)(Math.random() * 1000));
            System.out.println("run = " + Thread.currentThread().getName());
        }
    }
    catch (InterruptedException e)
    {
        e.printStackTrace();
    }
}

看下运行结果:

run = Thread-0
run = main
run = main
run = main
run = Thread-0
run = Thread-0

结果表明了:CPU执行哪个线程的代码具有不确定性。再看另外一个例子:

public class MyThread03 extends Thread
{
    public void run()
    {
        System.out.println(Thread.currentThread().getName());
    }
}
public static void main(String[] args)
{
    MyThread03 mt0 = new MyThread03();
    MyThread03 mt1 = new MyThread03();
    MyThread03 mt2 = new MyThread03();

    mt0.start();
    mt1.start();
    mt2.start();
}

看下运行结果:

Thread-1
Thread-2
Thread-0

尽管启动线程是按照mt0、mt1、mt2,但是实际的启动顺序却是Thread-1、Thread-2、Thread-0。这个例子说明了:调用start()方法的顺序不代表线程启动的顺序,线程启动顺序具有不确定性

关于start线程可以了解下多线程 Thread.currentThread().getName() ,对象实例.getName() 和 this.getName()区别 理解采用Thread继承实现线程的几种启动方式出现的问题

2、run()

线程开始执行,虚拟机调用的是线程run()方法中的内容。稍微改一下之前的例子看一下:

public static void main(String[] args)
{
    MyThread02 mt = new MyThread02();
    mt.run();

    try
    {
        for (int i = 0; i < 3; i++)
        {
            Thread.sleep((int)(Math.random() * 1000));
            System.out.println("run = " + Thread.currentThread().getName());
        }
    }
    catch (InterruptedException e)
    {
        e.printStackTrace();
    }
}

MyThread02的代码不变,看下运行结果:

run = main
run = main
run = main
run = main
run = main
run = main

看到打印了6次的"run = main",说明如果只有run()没有start(),Thread实例run()方法里面的内容是没有任何异步效果的,全部被main函数执行。换句话说,只有run()而不调用start()启动线程是没有任何意义的。

3、isAlive()

测试线程是否处于活动状态,只要线程启动且没有终止,方法返回的就是true。看一下例子:

public class MyThread06 extends Thread
{
    public void run()
    {
        System.out.println("run = " + this.isAlive());
    }
}
public static void main(String[] args) throws Exception
{
    MyThread06 mt = new MyThread06();
    System.out.println("begin == " + mt.isAlive());
    mt.start();
    Thread.sleep(100);
    System.out.println("end == " + mt.isAlive());
}

看下运行结果:

begin == false
run = true
end == false

看到在start()之前,线程的isAlive是false,start()之后就是true了。main函数中加上Thread.sleep(100)的原因是为了确保Thread06的run()方法中的代码执行完,否则有可能end这里打印出来的是true,有兴趣可以自己试验一下。

isAlive() 备注下

也就是 无论什么情况  sleep  wait 等 只要是还没结束  那isAlive()都是存活的

4、getId()

这个方法比较简单,就不写例子了。在一个Java应用中,有一个long型的全局唯一的线程ID生成器threadSeqNumber,每new出来一个线程都会把这个自增一次,并赋予线程的tid属性,这个是Thread自己做的,用户无法执行一个线程的Id。

5、getName()

这个方法也比较简单,也不写例子了。我们new一个线程的时候,可以指定该线程的名字,也可以不指定。如果指定,那么线程的名字就是我们自己指定的,getName()返回的也是开发者指定的线程的名字;如果不指定,那么Thread中有一个int型全局唯一的线程初始号生成器threadInitNum,Java先把threadInitNum自增,然后以"Thread-threadInitNum"的方式来命名新生成的线程

6、getPriority()和setPriority(int newPriority)

参考 java 多线程4: java线程的优先级

7、isDaeMon、setDaemon(boolean on)

讲解两个方法前,首先要知道理解一个概念。Java中有两种线程,一种是用户线程,一种是守护线程。守护线程是一种特殊的线程,它的作用是为其他线程的运行提供便利的服务,最典型的应用便是GC线程。如果进程中不存在非守护线程了,那么守护线程自动销毁,因为没有存在的必要,为别人服务,结果服务的对象都没了,当然就销毁了。

理解了这个概念后,看一下例子

public class MyThread11 extends Thread
{
    private int i = 0;

    public void run()
    {
        try
        {
            while (true)
            {
                i++;
                System.out.println("i = " + i);
                Thread.sleep(1000);
            }
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }
}
public static void main(String[] args)
    {
        try
        {
            MyThread11 mt = new MyThread11();
            mt.setDaemon(true);
            mt.start();
            Thread.sleep(5000);
            System.out.println("我离开thread对象再也不打印了,我停止了!");
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }

看一下运行结果:

 1 i = 1
 2 i = 2
 3 i = 3
 4 i = 4
 5 i = 5
 6 我离开thread对象再也不打印了,我停止了!
 7 i = 6

要解释一下。我们将MyThread11线程设置为守护线程,看到第6行的那句话,而i停在6不会再运行了。这说明,main线程运行了5秒多结束,而i每隔1秒累加一次,5秒后main线程执行完结束了,MyThread11作为守护线程,main函数都运行完了,自然也没有存在的必要了,就自动销毁了,因此也就没有再往下打印数字。

关于守护线程,有一个细节注意下,setDaemon(true)必须在线程start()之前

8、interrupt()

9、isInterrupted()

以上两个方法请转移

java 多线程5: java 终止线程及中断机制 (stop()、interrupt() 、interrupted()、isInterrupted())

java 多线程6: 中断机制 优雅的终止java线程  这两篇文章

10、join()

参考java多线程16:join()的使用

11.stop() 停止方法  已废弃

12.suspend() 和 resume() 暂停和恢复 ,已废弃

参考 java 多线程7: (suspend方法与resume方法) 挂起与恢复

时间: 2024-10-07 18:22:04

java 多线程2:Thread的实例方法的相关文章

Java 多线程(1)-Thread和Runnable

一提到Java多线程,首先想到的是Thread继承和Runnable的接口实现 Thread继承 public class MyThread extends Thread { public void run(){ int i = 0; System.out.println("--------------"+i++); } } Runnable接口实现 public class RunnableImpl implements Runnable { private long value =

Java多线程extends Thread和implements Runnable

大家都知道,要实现Java多线程的两种方式 a:是直接继承Thread类,b:是实现Runnable接口. 先上代码: a:是直接继承Thread类, public class ThreadDemo1 extends Thread {    public void run(){        //Thread.currentThread().getName() 和 this.getName()都可以用来获得线程的名称        System.out.println("线程的名称:"

Java多线程01(Thread类、线程创建、线程池)

Java多线程(Thread类.线程创建.线程池) 第一章 多线程 1.1 多线程介绍 1.1.1 基本概念 进程:进程指正在运行的程序.确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能. 线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程.一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序. 简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程 1.1.2 单线程程序 - 从入口m

java多线程创建-Thread,Runnable,callable和threadpool

java创建多线程的方式有许多种,这里简要做个梳理 1. 继承Thread类 继承java.lang.Thread类,创建本地多线程的类,重载run()方法,调用Thread的方法启动线程.示例代码如下: MyThread.java public class MyThread extends Thread { public void run(){ private int copy = 0; System.out.println("Thread id:" + Thread.current

Java 多线程之 Thread 类 和 Runnable 接口初步使用

Thread 类 Thread 类是在 JDK1.0 时就存在的, 在 Java 中接触的多线程开发基本上都会从这个类开始. Thread之定义线程类 使用 Thread 创建线程的方法很简单, Thread 是一个类, 在需要创建线程时, 我们只需要继承这个类, 并将 run() 方法进行重写即可. class PrimeThread extends Thread { long minPrime; PrimeThread(long minPrime) { this.minPrime = min

Java 多线程之--- Thread.join介绍

许久许久没有写过博客了,以前上班总是没有时间,但是总感觉写博客还是很好的一种记录自己技术进程的一种方式 于是在辞职后来到北软,又一次上学了,又一次有时间来写博客了,所以再次开始写博客了,呵呵,再次当学生的感觉 真好!!!! 这次说的是Thread的join方法,以前总是使用他的run和sleep方法,哪两个都是比较清楚的,对于这个join方法,他的 主要功能就是,当你在一个方法里面调用其他的线程的时候,如果使用了类似thread1.join(),这样的话,这个调用的线程 就开始一直等待threa

Java 多线程 (Thread 类)

1.多线程 1.多线程实现 两种方式可以实现多线程: 继承 Thread 类,重写 run 方法:定义对象,调用 start 方法 创建类实现 Runnable 接口,作为实参传递给 thread 的构造方法.定义对象,调用 start 方法. 1.1.继承 Thread 继承类,重写方法 class TDemo1 extends Thread { public String name; // 取个名字,便于识别 public TDemo1 (String name) { // 构造方法 thi

Java多线程之 Thread VS Runnable 【带案例】

为此,我们举个例子,假设有火车站有三个窗口,在卖火车票,总共只有5张票.每一个线程相当于一个窗口,分别售票 <strong>package com.thread; class myThread extends Thread{ private int ticketsCount=5;//一种有5张票 private String name;//窗口,也即是线程的名字 public myThread(String name){ this.name=name; } @Override public v

java 多线程 继承Thread和实现Runnable的区别

1)继承Thread: public class ThreadTest extends Thread { private int count; private String name; public ThreadTest(int count,String name){ this.count = count; this.name = name; } public void run() { while(count>0) { System.out.println(name+"买票 "+