Java多线程总结_优先级

Java 多线程总结

 

线程的四种状态:

 

就绪Runable ——运行中Running ——阻塞Blocked ——死亡Dead( 结束)

 

  线程的状态转换图

 

线程在一定条件下,状态会发生变化。线程变化的状态转换图如下:

1 、新建状态(New

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

3 、运行状态(Running ):就绪状态的线程获取了CPU

4 、阻塞状态(Blocked ):阻塞状态是线程因为某种原因放弃CPU

(一)、等待阻塞:运行的线程执行wait() 方法,JVM

(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM

(三)、其他阻塞:运行的线程执行sleep() 或join() 方法,或者发出了I/O 请求时,JVM 会把该线程置为阻塞状态。当sleep() 状态超时、join() 等待线程终止或者超时、或者I/O

5 、死亡状态(Dead ):线程执行完了或者因异常退出了run()

线程的调度

1 、调整线程优先级:Java

 Java 线程的优先级用整数表示,取值范围是1~10 ,Thread

static int MAX_PRIORITY           线程可以具有的最高优先级,取值为10 。

static int MIN_PRIORITY           线程可以具有的最低优先级,取值为1 。

static int NORM_PRIORITY           分配给线程的默认优先级,取值为5

 Thread 类的setPriority() 和getPriority()

  每个线程都有默认的优先级。主线程的默认优先级为Thread.NORM_PRIORITY

线程的优先级有继承关系,比如A 线程中创建了B 线程,那么B 将和A

JVM 提供了10 个线程优先级,但与常见的操作系统都不能很好的映射。如果希望程序能移植到各个操作系统中,应该仅仅使用Thread

 2 、线程睡眠:Thread.sleep(long millis) 方法,使线程转到阻塞状态。millis 参数设定睡眠的时间,以毫秒为单位。当睡眠结束后,就转为就绪(Runnable

 3 、线程等待:Object 类中的wait() 方法,导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 唤醒方法。这个两个唤醒方法也是Object 类中的方法,行为等价于调用 wait(0)

 4 、线程让步:Thread.yield()

 5 、线程加入:join() 方法,等待其他线程终止。在当前线程中调用另一个线程的join()

 6 、线程唤醒:Object 类中的notify() 方法,唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个 wait 方法,在对象的监视器上等待。 直到当前的线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争;例如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。类似的方法还有一个notifyAll()

 

JAVA 多线程实现的两种模型

 

区别与联系:

l         Runnable 是 Thread 的接口,在大多数情况下 “ 推荐用接口的方式 ” 生成线程,因为接口可以实现多继承,况且 Runnable 只有一个 run 方法,很适合继承。

l         在使用 Thread 的时候只需要 new 一个实例出来,调用 start() 方法即可以启动一个线程。 Thread Test = new Thread();
Test.start();

l         在使用 Runnable 的时候需要先 new 一个实现 Runnable 的类的实例,之后,创建线程时将线程与该实例关联(其本质是让该线程执行时调用该实例中的 run 方法 )。

 

 

l         扩展Thread

class MyThread extends Thread  {
    public MyThread (String threadName) {
        super(threadName);
    }
    public void run() {
        System.out.println(getName() + "  线程运行开始!");
        for (int i = 0; i < 10; i++) {
            System.out.println(i + " " + getName());
            try {
                sleep((int) Math.random() * 10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(getName() + "  线程运行结束!");
    }
}
 
public class TestMyThread {
    public static void main(String[] rags) {
        System.out.println(Thread.currentThread().getName() + "  线程运行开始!");
        new MyThread ("A").start();
        new MyThread ("B").start();
        System.out.println(Thread.currentThread().getName() + "  线程运行结束!");
    }
}

运行结果:

main 线程运行开始!

main 线程运行结束!

A 线程运行开始!

0 A

1 A

B 线程运行开始!

2 A

0 B

3 A

4 A

1 B

5 A

6 A

7 A

8 A

9 A

A 线程运行结束!

2 B

3 B

4 B

5 B

6 B

7 B

8 B

9 B

B 线程运行结束!

 

程序启动运行main 时候,java 虚拟机启动一个进程,主线程main 在main() 调用时候被创建。随着调用MyThread 的两个对象的start

  在一个方法中调用Thread.currentThread().getName() 方法,可以获取当前线程的名字。在mian

  注意:start() 方法的调用后并不是立即执行多线程代码,而是使得该线程变为可运行态(Runnable

Thread.sleep() 方法调用目的是不让当前线程独自霸占该进程所获取的CPU

l         实现java.lang.Runnable

public class TestMyThread implements Runnable  {
     public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName() + "  线程运行开始!");
       TestMyThread  test = new TestMyThread  ();
        Thread thread1 = new Thread(test);
        Thread thread2 = new Thread(test);
        thread1.start();
        thread2.start();
        System.out.println(Thread.currentThread().getName() + "  线程运行结束!");
    }
     public void run() {
        System.out.println(Thread.currentThread().getName() + "  线程运行开始!");
        for (int i = 0; i < 10; i++) {
            System.out.println(i + " " + Thread.currentThread().getName());
            try {
                Thread.sleep((int) Math.random() * 10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName() + "  线程运行结束!");
    }
}

 

main 线程运行开始!

Thread-0 线程运行开始!

main 线程运行结束!

0 Thread-0

Thread-1 线程运行开始!

0 Thread-1

1 Thread-1

1 Thread-0

2 Thread-0

2 Thread-1

3 Thread-0

3 Thread-1

4 Thread-0

4 Thread-1

5 Thread-0

6 Thread-0

5 Thread-1

7 Thread-0

8 Thread-0

6 Thread-1

9 Thread-0

7 Thread-1

Thread-0 线程运行结束!

8 Thread-1

9 Thread-1

Thread-1 线程运行结束!

 

TestMitiThread1 类通过实现Runnable 接口,使得该类有了多线程类的特征。run ()方法是多线程程序的一个约定。所有的多线程代码都在run 方法里面。Thread 类实际上也是实现了Runnable

在启动的多线程的时候,需要先通过Thread 类的构造方法Thread(Runnable target) 构造出对象,然后调用Thread 对象的start()

 

实际上所有的多线程代码都是通过运行Thread 的start() 方法来运行的。因此,不管是扩展Thread 类还是实现Runnable 接口来实现多线程,最终还是通过Thread 的对象的API 来控制线程的,熟悉Thread 类的API

 

读解Thread 类API

构造方法摘要

Thread(Runnable target)              分配新的 Thread 对象。

Thread(String name)                  分配新的 Thread 对象。

  方法摘要

static Thread currentThread()          

说明:返回对当前正在执行的线程对象的引用。

void start()

说明:使该线程开始执行;Java 虚拟机调用该线程的 run 方法。

void stop()

说明:已过时,

void suspend()

说明:已过时。 该方法已经遭到反对,因为它具有固有的死锁倾向。

void resume()          

说明:该方法已过时,它只与 suspend() 一起使用,但 suspend()

static void sleep(long millis)

说明:在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。

static void sleep(long millis, int nanos)

说明:在指定的毫秒数加指定的纳秒数内让当前正在执行的线程休眠(暂停执行)。

static void yield()

说明:线程让权,暂停当前正在执行的线程对象,并执行其他线程。

void interrupt() :       说明:中断线程。

void join() :          

说明:等待其他线程终止。在当前线程中调用另一个线程的join()

void run()        说明:线程方法运行。

String toString()

说明:返回该线程的字符串表示形式,包括线程名称、优先级和线程组。