Java多线程编程-Thread API (三)


我们都知道在执行多线程的时候,我们调用start方法的时候,线程不会立即执行,因为需要获得CPU的执行权之后才能运行线程。但是我们也可以让执行的线程放弃CPU的执行权。

Thread.yield()方法

yield():给调度程序的提示是当前线程愿意放弃当前使用的处理器。调度程序可以随意忽略此提示
Yield是一种启发式尝试,旨在提高线程之间的相对进程,否则将过度利用CPU。它的使用应与详细的性能分析和基准测试结合使用,以确保它确实具有所需的效果
很少适合使用此方法。它可能对调试或测试有用,因为它可能有助于重现由于竞争条件而产生的错误。当设计诸如java.util.concurrent.locks包中的并发控制结构时,它也可能很有用
源码:

public static native void yield();

我们先调用这个方法:

public class ThreadYieldV1 extends Thread {
    @Override
    public void run() {
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 20000; i++) {
            System.out.println("current i value:" + i);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("use total time:" + (endTime - startTime));
    }
}

运行代码:

public class ThreadYieldV1Main {

    public static void main(String[] args) {
        ThreadYieldV1 threadYieldV1 = new ThreadYieldV1();
        threadYieldV1.start();
    }
}

运行结果:
在这里插入图片描述

总共运行时间为450ms,当我们调用yield方法,让到暂时放弃CPU的执行权,看看时间。yield放弃之后有可能会立即获得,这个是不确定的。

public class ThreadYieldV1 extends Thread {

    @Override
    public void run() {
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 20000; i++) {
            Thread.yield();
            System.out.println("current i value:" + i);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("use total time:" + (endTime - startTime));
    }
}

运行结果:
在这里插入图片描述
调用yield方法让出CPU的执行权,所以时间会有有所增加。

守护进程

在Java中有两种线程,一种是用户线程,一种是守护线程
守护线程是一种特殊的线程,当进程中不存在非守护线程了,则守护线程自动销毁。典型的守护线程为垃圾回收线程。当进程中没有非守护线程,则垃圾回收线程就没有必要存在了,自动销毁。
声明为守护线程,使用setDaemon

Thread.setDaemon()方法

setDaemon():将此线程标记为isDaemon守护程序线程或用户线程。当所有正在运行的线程都是守护程序线程时,Java虚拟机将退出。
必须在线程启动之前调用此方法。

源码:

 public final void setDaemon(boolean on) {
        checkAccess();
        if (isAlive()) {
            throw new IllegalThreadStateException();
        }
        daemon = on;
    }

如果我们在线程start之后调用setDaemon方法会抛出异常:
在这里插入图片描述
线程还会继续运行
我们将代码改变一下:

public class ThreadDaemonV1Main {

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            try {
                int i = 0;
                while (true) {
                    i++;
                    System.out.println("current i value:" + i);
                    Thread.sleep(1000);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        thread.setDaemon(true);
        thread.start();
        Thread.sleep(5000);
        System.out.println("end");
    }

}

运行结果:
在这里插入图片描述
为什么会停止呢?因为我们将thread 设置为了守护进程,但是主线程main线程已经运行完了。将没有这个主线程了(也就没有了非守护进程),所以会将守护线程自动销毁,所以会销毁thread守护线程。

Thread.setPriority()

我们知道多线程情况下,线程的运行是随机的,而不是有序的。但是我们可以对线程进行划分优先级,优先级较高的线程得到的CPU资源较多,可以帮助实现线程的执行顺序,判断哪一个线程有限执行。
setPriority():更改此线程的优先级。
首先,不带任何参数调用此线程的 checkAccess方法。这可能导致抛出SecurityException。否则,此线程的优先级将设置为指定的 newPriority 和该线程的线程组的最大允许优先级中的较小者。

源码:

public final static int MAX_PRIORITY = 10;
public final static int MIN_PRIORITY = 1;
/**
  * 分配给线程的默认优先级
  */
 public final static int NORM_PRIORITY = 5;
public final void setPriority(int newPriority) {
        ThreadGroup g;
        checkAccess();
        if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
            throw new IllegalArgumentException();
        }
        if((g = getThreadGroup()) != null) {
            if (newPriority > g.getMaxPriority()) {
                newPriority = g.getMaxPriority();
            }
            setPriority0(priority = newPriority);
        }
    }

我们看看init方法中的一段代码:
在这里插入图片描述
说明线程的优先级默认是取父级的线程优先级。我们创建两个线程测试一下:

public class ThreadPriorityV102 extends Thread {
    @Override
    public void run() {
        System.out.println("02:" + this.getPriority());
    }
}

第二个线程:

public class ThreadPriorityV101 extends Thread {

    @Override
    public void run() {
        System.out.println("01:" + this.getPriority());
        ThreadPriorityV102 threadPriorityV102 = new ThreadPriorityV102();
        threadPriorityV102.start();
    }
}

运行代码:

public class ThreadPriorityV1Main {
    public static void main(String[] args) {
        System.out.println("main thread priority:" + Thread.currentThread().getPriority());
        ThreadPriorityV101 threadPriorityV101 = new ThreadPriorityV101();
        threadPriorityV101.start();
    }
}

运行结果:
在这里插入图片描述
从运行来开,这里的线程优先级都是默认的,默认取的是parent的优先级。
Main线程的优先级为最上层的,优先级为默认的5,main线程的子线程(ThreadPriorityV101 )没有设置,默认取父级的优先级,这里就是取main线程的优先级,ThreadPriorityV101 的子线程(ThreadPriorityV102 )也没有设置优先级,所以也是取ThreadPriorityV101 的优先级,所以都为5
所以由上的结论为如果没有设置线程优先级,这里取父节点的优先级,有优先级继承关系。
我们将设置线程ThreadPriorityV101 的优先级,ThreadPriorityV102 的优先级会和ThreadPriorityV101 一致

public class ThreadPriorityV1Main {

    public static void main(String[] args) {
        System.out.println("main thread priority:" + Thread.currentThread().getPriority());
        ThreadPriorityV101 threadPriorityV101 = new ThreadPriorityV101();
        threadPriorityV101.setPriority(8);  //设置ThreadPriorityV101的优先级
        threadPriorityV101.start();
    }
}

运行结果:
在这里插入图片描述
由此结论是正确的。
我们进行进一步优先级设置高的会执行,并不是说优先级的搞的先执行玩。我们说了线程的执行顺序是随机的,设置优先级只是说明哪一个先执行。并不是说设置高的优先级的线程会先执行完。
线程1:

public class ThreadPriorityV201 extends Thread {

    @Override
    public void run() {
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < 20000; j++) {
                Random random = new Random();
                random.nextInt();
                j++;
            }
        }
        long endTime = System.currentTimeMillis();
        System.out.print("thread1 run total time:" + (endTime - startTime));
    }
}

线程2:

public class ThreadPriorityV202 extends Thread {

    @Override
    public void run() {
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < 20000; j++) {
                Random random = new Random();
                random.nextInt();
                j++;
            }
        }
        long endTime = System.currentTimeMillis();
        System.out.println("thread2 run total time:" + (endTime - startTime));
    }
}

运行代码:

public class ThreadPriorityV2Main {
    public static void main(String[] args) {
        ThreadPriorityV201 threadPriorityV201 = new ThreadPriorityV201();
        threadPriorityV201.setPriority(Thread.MAX_PRIORITY);  //设置为最大的优先级
        threadPriorityV201.start();
        ThreadPriorityV202 threadPriorityV202 = new ThreadPriorityV202();
        threadPriorityV202.setPriority(Thread.MIN_PRIORITY); //设置为最小的优先级
        threadPriorityV202.start();
    }
}

运行结果:
在这里插入图片描述
可以多运行几次,大部分是线程ThreadPriorityV201 先运行完,但是也会出现上面的结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值