16.4控制线程

 Java提供线程控制的工具方法。

16.4.1 join线程

Thread提供了让一个线程等待另外一个线程完成的方法join()方法。当在某个线程执行流中调用其他线程的join()方法时,调用线程将被阻塞,直到被join()方法加入的join线程执行完为止。

PS:join方法通常使用线程的程序调用,以将大问题划分成许多小问题,每个小问题分配一个线程。当所有小线程都完成后,再调用主线程来操作。

package com.cdmt.collection.list;

public class JoinThread extends Thread {

    //提供一个带参构造器
    public JoinThread(String name){
        super(name);
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            //获取当前线程
            System.out.println(Thread.currentThread().getName() + "---" + i);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        //启动子线程
        new JoinThread("新线程").start();
        for(int i = 0; i<100; i++){
            if(i == 20){
                JoinThread jt = new JoinThread("被Join的线程");
                jt.start();
                //main线程调用了jt的join方法,main线程必须等待jt执行完毕
                jt.join();
            }
            System.out.println(Thread.currentThread().getName() + "---" + i);
        }
    }
}

结果:

java实现spc控制线算法 java控制线程_java实现spc控制线算法

 

java实现spc控制线算法 java控制线程_java实现spc控制线算法_02

总结:

共3线程,主方法开始时启动新线程,该线程将会和main线程并发执行。当主线程i变为20时,启动被Join的线程,main线程必须等待Join完成才可以执行。在被Join的线程执行时,实际上只有2个子线程并发执行,main线程处于等待状态。

join()方法有三种重载形式:

  1. join():等待被join的线程执行完毕
  2. join(long millis):等待被join的线程的时间最长为millis毫秒,如果在millis毫秒内被join的线程还没执行结束,则不再等待。
  3. join(long mills,int nanos):等待被join的线程的时间最长为millis毫秒加nanos毫微妙

16.4.2 后台线程

 有一种线程在后天运行,它的任务就是为其他线程提供服务,这种线程被称为后天线程(Daemon Thread),又被称为守护线程或者精灵线程。JVM的垃圾回收线程就是一个典型的后台线程。

后台线程有个特征:如果所有的前台程序都死亡,后台线程会自动死亡。

调用Thread对象的setDaemon(true)方法可以将指定线程设置成后台线程。当前台线程都死亡时,后台线程随之死亡。

package com.cdmt.collection.list;

public class DaemonThread extends Thread {



    //定义后台线程的线程执行体与普通线程没有任何区别
    @Override
    public void run() {
        for(int i=0; i<1000;i++){
            System.out.println(Thread.currentThread().getName() + "---" + i);
        }
    }

    public static void main(String[] args) {
        DaemonThread dt = new DaemonThread();
        //将此线程设置成后台线程
        dt.setDaemon(true);
        //启动后台线程
        dt.start();
        for(int i=0;i<10;i++){
            System.out.println(Thread.currentThread().getName() + "---" + i);
        }
        //程序执行到此处,前台线程main结束
        //后台线程也应该随之结束
    }
}

结果:

java实现spc控制线算法 java控制线程_后台线程_03

java实现spc控制线算法 java控制线程_java实现spc控制线算法_04

总结:

本来子线程要到999才会结束,但是由于前天线程全部死了,所以后台线程也就被JVM杀死。

PS:前台线程死亡后JVM通知后台线程死亡,但从它接收指令到做出响应,需要一定时间而且要将某个线程设直为后台线程,必须在该线程启动之前设置,也就是说setDaemon( true) 须在 start() 方法之前调用,否则会引发IllegalThreadStateException异常。

16.4.3 线程睡眠:sleep

如果需要让当前执行的线程 暂停一段时间,并进入阻塞状态,则可以通过调用Thread类的静态sleep()方法实现。

sleep有2种重载形式:

  1. static void sleep(long millis):让当前正在执行的线程暂停millis毫秒,并进入阻塞状态,该方法受到系统计时器和线程调度器的精度与准度影响
  2. static void sleep(long millis, int nanos):让当正在执行的线程暂停millis毫秒加nanos毫微妙,该方法受到系统计时器和线程调度器的精度与准度影响

与前面类似的是,程序很少调用第二种形式的sleep方法。

当前线程调用sleep方法进入阻塞状态后,在其睡眠时间段内,该线程不会获得执行的机会,即使系统中没有其他可执行的线程,处于sleep方法中的线程也不会执行,因此sleep方法常用来暂停程序的执行。

package com.cdmt.collection.list;

import java.util.Date;

public class SleepTest extends Thread {
    public static void main(String[] args) throws InterruptedException {
        for(int i=0;i<10;i++){
            System.out.println("当前时间是: "  + new Date());
            Thread.sleep(2000);
        }
    }
}

结果:

java实现spc控制线算法 java控制线程_后台线程_05

总结:

系统完全让出资源,每2s之后继续调用执行。yeild()方法只是让线程进入就绪状态,优先级比当前线程大或者相等的才可以得到资源。否则线程会继续执行。

16.4.4 改变线程优先级

 每个线程都有优先级,优先级高的线程获得执行机会比较多。每个线程默认的优先级都与创建它的父线程的优先级相同,在默认情况下,main线程具有普通优先级,由main线程创建的子线程也具有普通优先级。

Thread提供了setPriority(int newPriority)、getPriority()方法来设置和返回指定线程的优先级,其中setPriority()方法的参数可以是一个整数,范围是1-10之间,也可以使用Thread类如下的三个静态常量。

  1. MAX_PRIORITY:其值是10
  2. MIN_PRIORITY:其值是1
  3. NORM_PRIORITY:其值是5

 下面程序使用了setPriority方法来改变主线程的优先级

package com.cdmt.collection.list;

public class PriorityTest extends Thread {

    //定义一个有参数的构造器,用于创建线程时指定name
    public PriorityTest(String name){
        super(name);
    }

    @Override
    public void run() {
        for(int i=0;i<50;i++){
            System.out.println(getName() + ",其优先级是: " + getPriority() + ",循环变量的值为:" + i);
        }
    }

    public static void main(String[] args) {
        Thread.currentThread().setPriority(6);
        for(int i=0; i<30; i++){
            if(i==10){
                PriorityTest low = new PriorityTest("低级");
                low.start();
                System.out.println("创建之初的优先级: " + low.getPriority());
                low.setPriority(Thread.MIN_PRIORITY);
            }
            if(i==20){
                PriorityTest high = new PriorityTest("高级");
                high.start();
                System.out.println("创建之初的优先级: " + high.getPriority());
                high.setPriority(Thread.MAX_PRIORITY);
            }
        }
    }
}

结果:

java实现spc控制线算法 java控制线程_优先级_06

总结:

设置高的优先级有限运行。