线程常用方法(二)


后台线程:

说明:后台进程也成为守护进程,通过调用setDaemon(true)设置为后台进程。主线程默认为前台线程。

特征:如果前台进程都死亡,后台进程会自动死亡。

注意:setDaemon(true)必须在start()方法之前调用,否则会引发异常IllegalThreadStateException异常

示例代码:

package method;

/**
 * @Author YangHe
 * @Date 2020/4/8 17:51
 * 目的:其他进程执行完成,守护进程自动消亡,不管守护进程是否执行完毕
 */
public class ThreadDaemon extends Thread{

    public ThreadDaemon(String name){
        super(name); //设置线程名字
    }
    @Override
    public void run() {
        for(int i=0;i<10;i++){
            if(i==8&&getName().equals("守护线程")){ //如果是守护进程,睡眠保证执行进程先完成
                try {
                    sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(getName()+"输出"+i);
        }
    }
    public static void main(String[] args) throws InterruptedException {
        ThreadDaemon threadDaemon=new ThreadDaemon("守护线程");
        ThreadDaemon threadDaemon2=new ThreadDaemon("执行线程");
        threadDaemon.setDaemon(true); //将进程设置为守护进程
        threadDaemon.start();
        threadDaemon2.start();
    }
}

示例结果:

线程等待:join

说明:Thread提供了一个让一个线程等待另外一个线程完成的方法 join,调用join()方法,其他线程进入阻塞状态,等待该线程之执行完成,再进入就绪状态。

解决的实际问题:将一个大问题划分为许多小问题,每个小问题分配一个线程,这样所有小问题都解决完成,主线程来进行进一步不解决。

示例代码:

package method;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * @Author YangHe
 * @Date 2020/4/8 16:34
 * 目的:线程壹号等待线程贰号执行完毕开始执行
 */
public class ThreadJoin implements Callable {

    @Override
    public Integer call() throws Exception {
        int i=0;
        for(;i<100;i++){
            System.out.println(Thread.currentThread().getName()+" 线程执行完成度 i "+i);
        }
        return i;
    }

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ThreadJoin threadJoin=new ThreadJoin();
        FutureTask futureTask=new FutureTask(threadJoin);
        FutureTask futureTask2=new FutureTask(threadJoin);
        for(int j=0;j<100;j++){
            if(j==50){
                Thread thread=new Thread(futureTask,"线程壹号");
                Thread thread2=new Thread(futureTask2,"线程贰号");
                thread2.start();
                thread2.join();//等待该线程执行完毕才往下执行
                thread.start();
                System.out.println("线程壹号等待线程贰号完成开始执行。。。");
            }
        }
        System.out.println("线程贰号输出返回值:");
        System.out.println(futureTask2.get());
    }

}

示例结果【可看出最后才输出返回值】:

线程睡眠:sleep

说明:让当前线程暂停一段时间,让出处理器资源,进入阻塞状态。

当睡眠时间达到,该进程将会重新进入就绪状态。

示例代码:

package method;

/**
 * @Author YangHe
 * @Date 2020/4/8 16:18
 * 目的:实现到一定的程度进行睡眠,让出资源让其他线程执行
 */
public class ThreadSleep extends Thread {

    public ThreadSleep(String name){
        super(name); //定义线程名称
    }

    @Override
    public void run() {
        super.run();
        for(int i=0;i<100;i++){
            System.out.println(getName()+"i的值为 "+i);
            if(i==50){
                System.out.println(getName()+"线程进入睡眠");
                try {
                    Thread.sleep(1000); //当i的值为50时随眠一秒,让出处理器资源,进入阻塞。
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    System.out.println(getName()+"线程睡眠结束");
                }
            }
        }
    }

    public static void main(String[] args) {
        ThreadSleep threadSleep=new ThreadSleep("线程壹号");
        ThreadSleep threadSleep2=new ThreadSleep("线程贰号");
        threadSleep.start();
        threadSleep2.start();
    }

}

示例结果:

线程让步:yield

说明:只有其他线程优先级与当前线程优先级相同或者更高,才会获得执行机会。

设置线程优先级方法setPriority()

 该方法和sleep方法相似,区别在于:

  • sleep()方法暂停线程不会理会优先级,而yield只会给优先级相同或者更高的线程。
  • sleep()方法让线程进入阻塞状态,而yield()方法让线程再次进入就绪状态,不会阻塞。可能该执行完yield()方法,立即再次获得处理器资源被执行。
  • sleep()方法声明抛出异常InterruptedException异常,所以调用sleep()方法时要么捕获该异常,要么显式声明抛出异常。而yield()方法则没有声明抛出任何异常。
  • sleep()比yield()有更好的移植性,通常不建议使用yield()方法来控制并发线程的执行。

示例代码:

package method;

/**
 * @Author YangHe
 * @Date 2020/4/8 17:16
 * 目的:级别低的线程给级别高的线程进行让步
 */
public class ThreadYield extends Thread{

    public ThreadYield(String  name){
        super(name);
    }
    @Override
    public void run() {
        for(int i=0;i<100;i++){
            System.out.println(getName()+"当前执行i "+i);
            if(i==20){
                System.out.println(getName()+"执行线程让步");
            }
        }
    }

    public static void main(String[] args) {
        ThreadYield threadYield=new ThreadYield("最小线程级别");
        threadYield.setPriority(MIN_PRIORITY);
        threadYield.start();
        ThreadYield threadYield2=new ThreadYield("最大线程级别");
        threadYield2.setPriority(MAX_PRIORITY);
        threadYield2.start();
    }
}

示例结果: