JAVA抢占式线程调度的问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA抢占式线程调度的问题相关的知识,希望对你有一定的参考价值。

以下程序为例:
public class ThreadTerminate
public static void main(String args[])/*throws Exception*/
int i = 0;
Hello h = new Hello();
Thread t = new Thread(h);
t.setPriority(Thread.MAX_PRIORITY);
t.start();
System.out.println("Please stop saying Hello and say good morning!");
h.stopRunning();
while(i<5)System.out.println("Good Moring"+ i++);



class Hello implements Runnable
int i=0;
private boolean timeToQuit = false;
public void run()
while(!timeToQuit)
System.out.println("Hello" + i++);
try
if(i%2==1)
Thread.sleep(1000000000);

catch(Exception e)


public void stopRunning()
timeToQuit = true;


运行结果:
please stop saying hello and say good morning!
hello0
Good Morning0
Good Morning1
Good Morning2
Good Morning3
Good Morning4
问题:1、主线程在占用CPU的时候线程 t 为什么可以把主线程从CPU赶出来?那是不是只要有多个线程处于可运行态,就可以在当前线程运行的任何时候插进去把当前线程挤出CPU?
2、如果是因为线程 t 的优先级最高,那么运行结果为什么不是
hello0
please stop saying hello and say good morning!
Good Morning0
Good Morning1
Good Morning2
Good Morning3
Good Morning4
小白啊,谢大神讲清晰点

1线程的调度并不是由java决定的,而是os,os可以保证所有线程都有机会得到执行。即时某个线程正在忙。也会被休眠。具体的你要看os相关的线程调度这一块,这叫抢占式任务调度。

2即使线程t的优先级高,在调用start时,也不会保证线程已经真实的启动。os只是把他放到了线程队列中去排队。而当前线程继续执行。
参考技术A 多线程是没有啥说法是说某个线程具有优先级,都是由CPU随机的让某一个线程在一个时间段里面运行。而线程有个特定的叫计数器的东西,这个东西是控制每个线程在运行后,将控制权交出去后又得到时,不会运行出错,所以你可以试试多写几个线程试一下结果。

多说一句,main方法你也知道是主线程,就像老大没带头,小弟会动吗?所以要等main运行完了子线程才开始运行,你可以多些几个线程看看子线程是不是这样的
参考技术B cpu是在不断切换执行任务的,priority高的获得cpu运行时间的概率高,并不意味着能把低的完全挤掉,执行是有随机性的

Java线程调度及相关函数

文章目录

Java线程调度

线程调度

  • 抢占式调度模型:
    那个线程的优先级比较高,抢到的CPU时间片的概率就高一些/多一些。
    java采用的就是抢占式调度模型

  • 均分式调度模型:
    平均分配CPU时间片。每个线程占有的CPU时间片时间长度一样。
    平均分配,一切平等。
    有一些编程语言,线程调度模型采用的是这种方式。

相关方法

线程实例方法:

void setPriority(int newPriority); 	// 设置线程的优先级
int getPriority(); 					// 获取线程优先级

注意:

  • 最低优先级1
  • 默认优先级是5
  • 最高优先级10

优先级比较高的获取CPU时间片可能会多一些。(但也不完全是,大概率是多的)。

void join();			// 让一个线程等待另一个线程完成的方法

当在某个程序执行流中调用其他线程的join()方法时,调用线程将被阻塞,直到被join()方法加入的join线程执行完为止。

join()方法通常由使用线程的程序调用,以将大问题划分成许多小问题,每个小问题分配一个线程。当所有的小问题都得到处理后,再调用主线程来进一步操作。

线程类静态方法:

static void yield(); 		// 让位方法

暂停当前正在执行的线程对象,并执行其他线程

yield()方法不是阻塞方法。让当前线程让位,让给其它线程使用。yield()方法的执行会让当前线程从“运行状态”回到“就绪状态”。

注意:在回到就绪之后,有可能还会再次抢到,然后过了很短时间就又运行了,所以可能会出现看起来像没调用yield()一样。

代码案例

设置线程优先级

package com.yyl.threadTest;

class MyThread extends Thread 
    @Override
    public void run() 
        // 获取线程优先级
        //System.out.println(Thread.currentThread().getName() + "线程的默认优先级:" + Thread.currentThread().getPriority());
        for (int i = 0; i < 10000; i++) 
            System.out.println(Thread.currentThread().getName() + "-->" + i);
        
    


public class ThreadScheduling 
    public static void main(String[] args) 
        // 设置主线程的优先级为1
        Thread.currentThread().setPriority(1);

        // 获取当前线程对象,获取当前线程的优先级
        Thread currentThread = Thread.currentThread();

        Thread t = new Thread(new MyThread());
        t.setPriority(10);
        t.setName("t");
        t.start();

        // 优先级较高的,只是抢到的CPU时间片相对多一些。
        // 大概率方向更偏向于优先级比较高的。
        for (int i = 0; i < 10000; i++) 
            System.out.println(Thread.currentThread().getName() + "-->" + i);
        

        // 最高优先级:10
        // 最低优先级:1
        // 默认优先级:5
        System.out.println("最高优先级:" + Thread.MAX_PRIORITY);
        System.out.println("最低优先级:" + Thread.MIN_PRIORITY);
        System.out.println("默认优先级:" + Thread.NORM_PRIORITY);
    


调用yield暂停当前线程

package com.yyl.threadTest;

class MyThread extends Thread 
    @Override
    public void run() 
        for(int i = 1; i <= 10000; i++) 
            //每100个让位一次。
            if(i % 100 == 0)
                Thread.yield(); // 当前线程暂停一下,让给主线程
            
            System.out.println(Thread.currentThread().getName() + "--->" + i);
        
    


public class ThreadScheduling 
    public static void main(String[] args) 
        Thread t = new Thread(new MyThread());
        t.setName("t");
        t.start();

        for(int i = 1; i <= 10000; i++) 
            System.out.println(Thread.currentThread().getName() + "--->" + i);
        
    

以上是关于JAVA抢占式线程调度的问题的主要内容,如果未能解决你的问题,请参考以下文章

java线程调度

Java线程调度及相关函数

Java线程调度及相关函数

Java多线程的调度策略

多线程

java多线程的调度策略