Java线程Thread及其常用方法

Java SE7 API - Thread: http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#yield%28%29

一、线程的简介

当JVM启动的时候, 通常会有一个独立的非守护线程(也就是类中的main方法所在的线程).JVM会继续运行,除非发生以下情况:

Runtime类的exit()方法被调用,并且安全管理者允许退出发生。

所有非守护线程都已经死了,不管是从run方法中返回的还是因为run方法中抛出了异常。

注意:当所有非守护线程都执行结束(包括主线程),那么守护线程也会退出。因为守护线程是无法脱离非守护线程而独自存在的。

二、创建线程有两种方式:

方法1:声明一个类作为Thread的子类(extends Thread),子类重写(override)Thread类的run()方法。子类的实例可以被分配和start。

    //比如:该线程用来计算比指定起始值大的素数。
    class PrimeThread extends Thread {
         long minPrime;
         PrimeThread(long minPrime) {
             this.minPrime = minPrime;
         }

         public void run() {
             // compute primes larger than minPrime
              . . .
         }
     }
     //以下代码用来创建和启动线程PrimeThread 
     PrimeThread p = new PrimeThread(143);
     p.start();

方法2: 声明一个实现Runnable接口的类(implements Runnable),该类实现run()方法。该类的实例可以被分配,或者在创建Thread时作为一个参数,并且start.

    class PrimeRun implements Runnable {
         long minPrime;
         PrimeRun(long minPrime) {
             this.minPrime = minPrime;
         }

         public void run() {
             // compute primes larger than minPrime
              . . .
         }
     }
     PrimeRun p = new PrimeRun(143);
     new Thread(p).start();

三、Thread的方法:

static intactiveCount() Returns an estimate of the number of active threads in the current thread‘s thread group and its subgroups.
StringgetName() Returns this thread‘s name.
intgetPriority() Returns this thread‘s priority.
Thread.State getState() Returns the state of this thread.
booleanisAlive() Tests if this thread is alive.
booleanisDaemon() Tests if this thread is a daemon thread.
booleanisInterrupted() Tests whether this thread has been interrupted.

最常用的方法

void join() Waits for this thread to die.
void join(long millis) Waits at most millis milliseconds for this thread to die.
void join(long millis, int nanos) Waits at most millis milliseconds plus nanos nanoseconds for this thread to die.
void run() If this thread was constructed using a separate Runnable run object, then that Runnable object‘s run method is called; otherwise, this method does nothing and returns.
void setDaemon(boolean on) Marks this thread as either a daemon thread or a user thread.
static void sleep(long millis) Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds, subject to the precision and accuracy of system timers and schedulers.
static void sleep(long millis, int nanos) Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds plus the specified number of nanoseconds, subject to the precision and accuracy of system timers and schedulers.
void start() Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread.
static void yield() A hint to the scheduler that the current thread is willing to yield its current use of a processor.

从java.long.Object继承来的方法:

? ? ? ?

protected voidfinalize() Called by the garbage collector on an object when garbage collection determines that there are no more references to the object.
void notify() Wakes up a single thread that is waiting on this object‘s monitor.
void notifyAll() Wakes up all threads that are waiting on this object‘s monitor.
void wait() Causes the current thread to wait until another thread invokes the notify() method or the notifyAll()method for this object.
void wait(long timeout) Causes the current thread to wait until either another thread invokes the notify() method or thenotifyAll() method for this object, or a specified amount of time has elapsed.
void wait(long timeout, int nanos) Causes the current thread to wait until another thread invokes the notify() method or the notifyAll()method for this object, or some other thread interrupts the current thread, or a certain amount of real time has elapsed.

注意事项

1.sleep-wait-yield区别

sleep是Thread类中的一个静态方法,在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响,如果指定睡眠的时间到达,则从阻塞状态转变成就绪状态,等待运行。 
    yield只是使当前线程重新回到可执行状态,让其它同一优先级的线程先运行,所以执行yield()的线程有可能进入到可执行状态后马上又被执行。

wait是Object类中定义的方法,与notify/notifyAll()在一起成对使用,提供线程间的等待-通知机制。

2.使用wait-notify 
    (1).调用notify是随机的唤醒某一thread.而notifyAll则是唤醒所有等待的线程, 但只有一个线程可以在唤醒后lock object monitor,所以, notifyAll操作也是有利弊的. 
    (2).wait、notify、notifyAll必须在synchronized修饰的代码块中执行,否则会在运行的时候抛出IllegalMonitorStateException异常 .
    (3).在循环语句wait的时候一定要设定循环的条件(while(flag))--这样能够避免wait开始之前,线程所需的条件已经被其他线程提供了却依然开始此线程wait导致的时间消耗。同时,这种办法还能够保证你的代码不被虚假的信息唤醒。 
    (4).总是要保证在调用notify和notifyAll之前,能够提供符合线程退出等待的条件。否则会出现即使线程接收到通知信息,却不能退出循环等待的情况。

3.join()方法 
  join方法是使当前线程阻塞,直到所引用的线程结束才激活.

4.synchronized关键字 
    synchronized有四种使用方式: 
         synchronized method(){} 
      synchronized (obj) 
      static synchronized method(){} 
      synchronized(classname.class) 
   前面两个使用的锁是对象monitor,后面两者使用的是类monitor,都可以实现互斥访问。 
一个对象只有一个对象monitor,一个类也只有一个类monitor。静态方法使用类monitor进行同步,而普通方法则使用对象monitor进行同步。

五、线程的状态 
线程有四种状态,任何一个线程肯定处于这四种状态中的一种: 
    1)产生(New):线程对象已经产生,但尚未被启动,所以无法执行。如通过new产生了一个线程对象后没对它调用start()函数之前。 
    2)可执行(Runnable):每个支持多线程的系统都有一个排程器,排程器会从线程池中选择一个线程并启动它。当一个线程处于可执行状态时,表示它可能正处于线程池中等待排排程器启动它;也可能它已正在执行。如执行了一个线程对象的start()方法后,线程就处于可执行状态,但显而易见的是此时线程不一定正在执行中。 
    3)死亡(Dead):当一个线程正常结束,它便处于死亡状态。如一个线程的run()函数执行完毕后线程就进入死亡状态。 
    4)停滞(Blocked):当一个线程处于停滞状态时,系统排程器就会忽略它,不对它进行排程。当处于停滞状态的线程重新回到可执行状态时,它有可能重新执行。如通过对一个线程调用wait()函数后,线程就进入停滞状态,只有当两次对该线程调用notify或notifyAll后它才能两次回到可执行状态。

代码示例:

public class Counter
{
    public AtomicInteger  inc = new AtomicInteger();
    public void increase()
    {
        inc.getAndIncrement();
    }
    public static void main(String[] args) throws InterruptedException
    {
        final Counter test = new Counter();
        for (int i = 0; i < 10; i++)
        {
            Thread t = new Thread()
            {
                @Override
                public void run()
                {
                    for (int j = 0; j < 10; j++)
                    {
                        test.increase();
                        System.out.println(Thread.currentThread().getName() + "----" + test.inc);
                    }
                };
            };
//            t.setDaemon(true);
            t.start();            
        }       
        
        while (Thread.activeCount() > 1)//保证前面的线程都执行完
        {
//            Thread.yield();
//            Thread.sleep(1);
//            System.out.println(Thread.currentThread().getName()+"-yield");
        }        
        System.out.println(test.inc);
        System.out.println("Thread.activeCount()="+Thread.activeCount());
    }
}

通过启用注释掉的部分可以得到不同的结果。

时间: 2024-10-09 15:11:12

Java线程Thread及其常用方法的相关文章

java 线程 --- Thread,Runnable,Callable 基础学习

java 使用 Thread 类代表线程,所有现场对象都必须是 Thread 类或者其子类的实例.每个线程的作用是完成一定的任务,实际上就是执行一段程序流.java 使用线程执行体来代表这段程序流. 1.继承Thread 类创建线程 启动多线程的步骤如下: (1)定义Thread 类的子类,并重写该类的run() 方法,该run() 方法的方法体就代表类线程需要完成的任务.因此把run() 方法称为线程执行体. (2)创建 Thread 子类的实例,即创建线程对象. (3)调用线程的star()

java 线程 Thread 使用介绍,包含wait(),notifyAll() 等函数使用介绍

(原创,转载请说明出处!谢谢) 目录: --线程的创建: --启动线程 --线程的调度 --Thread 类的简介 --线程的同步/异步 --wait() 和 notify(),notifyAll()方法 在讲线程之前,先说下进程. 进程是运行系统中,每个独立运行的程序.例如win7,我既用酷狗软件听歌,又玩 LOL 游戏,又上QQ,那么这就有3个进程. 线程:一个进程里面有很多线程,进程是由线程组成的,线程的结束不一定会导致进程结束,而一个进程的结束,则会连带它里面的所有线程被结束. ----

java线程-Thread和Runnable的区别

进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程. 线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小. 线程和进程一样分为五个阶段:创建.就绪.运行.阻塞.终止. 多进程是指操作系统能同时运行多个任务(程序). 多线程是指在同一程序中有多个顺序流在执行 在java中要想实现多线程,有两种手段,一种是继续Thread类,另外一种是实现Runable接口. Thread类是在java.lang包

Java线程Thread的创建

Java中线程的创建有两种方式: 1.  通过继承Thread类,重写Thread的run()方法,将线程运行的逻辑放在其中 2.  通过实现Runnable接口,实例化Thread类 第一种方式:继承Thread类 package com.yyx.thread; /** * 通过继承Thread类创建线程 * yyx 2018年2月4日 */ public class CreateThreadByextends { public static void main(String[] args)

java 线程Thread.Sleep详解(转载)

我们可能经常会用到 Thread.Sleep 函数来使线程挂起一段时间.那么你有没有正确的理解这个函数的用法呢? 思考下面这两个问题: 1.假设现在是 2008-4-7 12:00:00.000,如果我调用一下 Thread.Sleep(1000) ,在 2008-4-7 12:00:01.000 的时候,这个线程会 不会被唤醒? 2.某人的代码中用了一句看似莫明其妙的话:Thread.Sleep(0) .既然是 Sleep 0 毫秒,那么他跟去掉这句代码相比,有啥区别么? 我们先回顾一下操作系

Java线程Thread使用匿名内部类创建的两种方式

匿名内部类实现线程的两种方式: 第一种方式: 1.继承Thread类 2.重写run方法 3.将要执行的代码写在run方法中 第二种方式: 1.将Runnable的子类对象传递给Thread的构造方法 2.重写run方法 3.将执行的代码写在run方法中,最后我们开启线程 package com.yyx.thread; /** * 匿名内部类创建线程 yyx 2018年2月4日 */ public class AnonymousThread { public static void main(S

java 线程Thread 技术--创建线程的方式

在第一节中,对线程的创建我们通过看文档,得知线程的创建有两种方式进行实现,我们进行第一种方式的创建,通过继承Thread 类 ,并且重写它的run 方法,就可以进行线程的创建,所有的程序执行都放在了run 方法里:可以说run 方法里放入的是线程执行的程序:在执行线程的时候,需要调用线程的start 方法,就可以进行线程的启动: 总之就是:代码写在run 方法里面,但是线程的执行调用start 方法,start 方法会开启一个线程去执行run 方法: 方式-: public class Thre

java线程Thread的join方法。

1,方法的作用: 父线程等待子线程的执行. 如果是join或者join(0),即等待时长是0,父线程就会一直等到子线程执行结束, 如果是join(time),即等待时长是time数值,那父线程等待时长视情况而定: 第一种:子线程执行时长不需要time时长,那么父线程就可能不会等待到time时长,为什么是可能呢?是不是要考虑其他线程(不包括父线程,和子线程以外的线程),他也可能让父线程等待的(没有获取到cpu时间片等原因), 第二种:子线程执行时长超过time时长,那么父线程的等待时长,至少是ti

Java线程唤醒与阻塞常用方法有哪些?

如果线程是因为调用了wait().sleep()或者join()方法而导致的阻塞,可以中断线程,并且通过抛出InterruptedException来唤醒它:如果线程遇到了IO阻塞,无能为力,因为IO是操作系统实现的,Java代码并没有办法直接接触到操作系统.以下是详细的唤醒方法: 1. sleep() 方法 sleep(毫秒),指定以毫秒为单位的时间,使线程在该时间内进入线程阻塞状态,期间得不到cpu的时间片,等到时间过去了,线程重新进入可执行状态.(暂停线程,不会释放锁) 2.suspend