精华内容
下载资源
问答
  • 2018-08-27 16:45:00

    1.start(开启线程,start是通过线程来调用run方法)

    2.run   此run非彼run (不是在run方法实现线程的逻辑,而是thread.run(),这个run方法是直接调用了线程中的run)

    3.yield(暂停当前线程,并执行其他线程)

    4.sleep(使当前线程由运行状态变成阻塞状态,若睡眠时其他线程调用了interrupt方法,会导致sleep抛出异常InterruptException)

    5.join(保证当前线程在其他线程开始时会结束)(如下,A线程想运行的话,必须等B线程结束才能运行(将处于阻塞状态))

     Thread A{

    run{

    new ThreadB.join();

    }

    }.start;

    6.interrupt(中断线程)

    7.wait/notify(从Object类继承下来的方法)

    8.setPriority(设置线程优先级(只能在线程开始前设置))

    9.stop(强制结束线程)

    更多相关内容
  • thread类哪些方法

    千次阅读 2021-02-26 20:31:04
    Thread类中的方法可分为实例方法和静态方法,其中实例方法有start()方法,run()方法等,静态方法有currentThread()方法,sleep(long millis)方法等【推荐课程:Java教程】Thread类中的实例方法start()方法这个方法的...

    Thread类中的方法可分为实例方法和静态方法,其中实例方法有start()方法,run()方法等,静态方法有currentThread()方法,sleep(long millis)方法等

    6261dd4cb91c021c1071fcf357286eb1.png

    【推荐课程:Java教程】

    Thread类中的实例方法

    start()方法

    这个方法的作用就是通知线程规划器此现场可以运行了。要注意,调用start方法的顺序不代表线程启动的顺序,也就是cpu执行哪个线程的代码具有不确定性。

    run()方法

    这个方法是线程类调用start后所执行的方法,如果直接调用run而不是start方法,那么和普通方法一样没有区别

    isAlive()方法

    是判断当前线程是否处于活动状态。活动状态就是已经启动尚未终止。

    getPriority()和setPriority(int newPriority)方法

    这两个方法是用于获取当前和设置线程的优先级。优先级高的线程得到的cpu多。也就是说,两个等待的线程,优先级高的线程容易被cpu执行。默认情况下,线程的优先级是5。线程的优先级分为1~10等级。

    isDaeMon、setDaemon(boolean on)方法

    java线程有两种,一种是用户线程,一种是守护线程。守护线程是一个特殊的线程,任何一个守护线程都是jvm中所有非守护线程的保姆。当进程中不存在非守护线程时,守护线程会自动销毁。典型的守护线程就是垃圾回收线程。

    第一个方法是判断线程是不是守护线程,第二个方法是设置线程为守护线程,必须在线程start之前setDaemon(true)

    interrupt()方法

    使用这个方法不会中断线程。实际上调用interrupt实际作用是在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞状态。

    join()方法

    join方法会使得调用join方法的线程无限阻塞,直到调用join方法的线程销毁为止,join方法内部使用的是wait(),所以会释放锁。

    Thread类的静态方法

    currentThread()方法

    该方法返回的当前正在执行线程对象的引用。

    sleep(long millis)方法

    sleep方法的作用就是在指定的时间让正在执行的线程休眠。并不释放锁。

    yield()方法

    暂停当前执行的线程对象,并执行其他线程。这个暂停会放弃cpu资源,放弃的时间不确定

    Thread类中的方法调用方式

    调用Thread中的方法的时候,在线程类中,有两种方式:

    this.xxx()方式

    这种方式的线程是线程实例本身

    Thread.currentThread.xxx()或Thread.xxx()方式

    这种表示线程执行Thread.currenThread.xxx()所在代码块的线程。

    总结:以上就是本篇文章的全部内容了,希望对大家有所帮助。

    展开全文
  • thread 详解

    千次阅读 2021-03-04 01:20:01
    java.lang.Thread类详解一、前言位于java.lang包下的Thread类是非常重要的线程类,它实现了Runnable接口...二、线程的状态在正式学习Thread类中的具体方法之前,我们先来了解一下线程有哪些状态,这个将会有助于后面...

    java.lang.Thread类详解

    一、前言

    位于java.lang包下的Thread类是非常重要的线程类,它实现了Runnable接口,今天我们来学习一下Thread类,在学习Thread类之前,先介绍与线程相关知识:线程的几种状态、上下文切换,然后接着介绍Thread类中的方法的具体使用。

    二、线程的状态

    在正式学习Thread类中的具体方法之前,我们先来了解一下线程有哪些状态,这个将会有助于后面对Thread类中的方法的理解。

    线程从创建到最终的消亡,要经历若干个状态。一般来说,线程包括以下这几个状态:创建(new)、就绪(runnable)、运行(running)、阻塞(blocked)、time waiting、waiting、消亡(dead)。

    当需要新起一个线程来执行某个子任务时,就创建了一个线程。但是线程创建之后,不会立即进入就绪状态,因为线程的运行需要一些条件(比如内存资源,譬如程序计数器、Java栈、本地方法栈都是线程私有的,所以需要为线程分配一定的内存空间),只有线程运行需要的所有条件满足了,才进入就绪状态。

    当线程进入就绪状态后,不代表立刻就能获取CPU执行时间,也许此时CPU正在执行其他的事情,因此它要等待。当得到CPU执行时间之后,线程便真正进入运行状态。

    线程在运行状态过程中,可能有多个原因导致当前线程不继续运行下去,比如用户主动让线程睡眠(睡眠一定的时间之后再重新执行)、用户主动让线程等待,或者被同步块给阻塞,此时就对应着多个状态:time waiting(睡眠或等待一定的事件)、waiting(等待被唤醒)、blocked(阻塞)。

    当由于突然中断或者子任务执行完毕,线程就会被消亡。

    下面这副图描述了线程从创建到消亡之间的状态:

    ed67c49ef918d6ede446ee8e16870655.png

    在有些教程上将blocked、waiting、time waiting统称为阻塞状态,这个也是可以的,只不过这里我想将线程的状态和Java中的方法调用联系起来,所以将waiting和time waiting两个状态分离出来。

    三、上下文切换

    对于单核CPU来说(对于多核CPU,此处就理解为一个核),CPU在一个时刻只能运行一个线程,当在运行一个线程的过程中转去运行另外一个线程,这个叫做线程上下文切换(对于进程也是类似)。

    由于可能当前线程的任务并没有执行完毕,所以在切换时需要保存线程的运行状态,以便下次重新切换回来时能够继续切换之前的状态运行。举个简单的例子:比如一个线程A正在读取一个文件的内容,正读到文件的一半,此时需要暂停线程A,转去执行线程B,当再次切换回来执行线程A的时候,我们不希望线程A又从文件的开头来读取。

    因此需要记录线程A的运行状态,那么会记录哪些数据呢?因为下次恢复时需要知道在这之前当前线程已经执行到哪条指令了,所以需要记录程序计数器的值,另外比如说线程正在进行某个计算的时候被挂起了,那么下次继续执行的时候需要知道之前挂起时变量的值时多少,因此需要记录CPU寄存器的状态。所以一般来说,线程上下文切换过程中会记录程序计数器、CPU寄存器状态等数据。

    说简单点的:对于线程的上下文切换实际上就是 存储和恢复CPU状态的过程,它使得线程执行能够从中断点恢复执行。

    虽然多线程可以使得任务执行的效率得到提升,但是由于在线程切换时同样会带来一定的开销代价,并且多个线程会导致系统资源占用的增加,所以在进行多线程编程时要注意这些因素。

    四、Thread类中的方法

    通过查看java.lang.Thread类的源码可知:

    c44ea3aa37fa6c6969a5644b327a1561.png

    Thread类实现了Runnable接口,在Thread类中,有一些比较关键的属性,比如name是表示Thread的名字,可以通过Thread类的构造器中的参数来指定线程名字,priority表示线程的优先级(最大值为10,最小值为1,默认值为5),daemon表示线程是否是守护线程,target表示要执行的任务。

    下面是Thread类中常用的方法:

    以下是关系到线程运行状态的几个方法:

    1)start方法

    start()用来启动一个线程,当调用start方法后,系统才会开启一个新的线程来执行用户定义的子任务,在这个过程中,会为相应的线程分配需要的资源。

    2)run方法

    run()方法是不需要用户来调用的,当通过start方法启动一个线程之后,当线程获得了CPU执行时间,便进入run方法体去执行具体的任务。注意,继承Thread类必须重写run方法,在run方法中定义具体要执行的任务。

    3)sleep方法

    sleep方法有两个重载版本:

    1

    2

    sleep(long millis)//参数为毫秒

    sleep(long millis,int nanoseconds)//第一参数为毫秒,第二个参数为纳秒

    sleep相当于让线程睡眠,交出CPU,让CPU去执行其他的任务。

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

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

    但是有一点要非常注意,sleep方法不会释放锁,也就是说如果当前线程持有对某个对象的锁,则即使调用sleep方法,其他线程也无法访问这个对象。看下面这个例子就清楚了:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    public class Test {

    private int i =10;

    private Object object =new Object();

    public static void main(String[] args)throwsIOException  {

    Test test =new Test();

    MyThread thread1 = test.new MyThread();

    MyThread thread2 = test.new MyThread();

    thread1.start();

    thread2.start();

    }

    class MyThreadextends Thread{

    @Override

    public void run() {

    synchronized (object) {

    i++;

    System.out.println("i:"+i);

    try {

    System.out.println("线程"+Thread.currentThread().getName()+"进入睡眠状态");

    Thread.currentThread().sleep(10000);

    }catch(InterruptedException e) {

    // TODO: handle exception

    }

    System.out.println("线程"+Thread.currentThread().getName()+"睡眠结束");

    i++;

    System.out.println("i:"+i);

    }

    }

    }

    }

    输出结果:

    486249076b27c506ef1ffa5204787f18.png

    从上面输出结果可以看出,当Thread-0进入睡眠状态之后,Thread-1并没有去执行具体的任务。只有当Thread-0执行完之后,此时Thread-0释放了对象锁,Thread-1才开始执行。

    注意,如果调用了sleep方法,必须捕获InterruptedException异常或者将该异常向上层抛出。当线程睡眠时间满后,不一定会立即得到执行,因为此时可能CPU正在执行其他的任务。所以说调用sleep方法相当于让线程进入阻塞状态。

    4)yield方法

    yield()方法和sleep()方法有点相似,它也是Thread类提供的一个静态方法,它也可以让当前正在执行的线程暂停,但它不会阻塞该线程,它只是将该线程转入到就绪状态。即让当前线程暂停一下,让系统的线程调度器重新调度一次,完全可能的情况是:当某个线程调用了yield()方法暂停之后,线程调度器又将其调度出来重新执行。

    调用yield方法会让当前线程交出CPU权限,让CPU去执行其他的线程。它跟sleep方法类似,同样不会释放锁。但是yield不能控制具体的交出CPU的时间,另外,当某个线程调用了yield()方法之后,只有优先级与当前线程相同或者比当前线程更高的处于就绪状态的线程才会获得执行机会。

    注意,调用yield方法并不会让线程进入阻塞状态,而是让线程重回就绪状态,它只需要等待重新获取CPU执行时间,这一点是和sleep方法不一样的。

    5)join方法

    join方法有三个重载版本:

    1

    2

    3

    join()

    join(long millis)//参数为毫秒

    join(long millis,int nanoseconds)//第一参数为毫秒,第二个参数为纳秒

    假如在main线程中,调用thread.join方法,则main方法会等待thread线程执行完毕或者等待一定的时间。如果调用的是无参join方法,则等待thread执行完毕,如果调用的是指定了时间参数的join方法,则等待一定的事件。

    看下面一个例子:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    public class Test {

    public static void main(String[] args)throwsIOException  {

    System.out.println("进入线程"+Thread.currentThread().getName());

    Test test =new Test();

    MyThread thread1 = test.new MyThread();

    thread1.start();

    try {

    System.out.println("线程"+Thread.currentThread().getName()+"等待");

    thread1.join();

    System.out.println("线程"+Thread.currentThread().getName()+"继续执行");

    }catch (InterruptedException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    class MyThreadextends Thread{

    @Override

    public void run() {

    System.out.println("进入线程"+Thread.currentThread().getName());

    try {

    Thread.currentThread().sleep(5000);

    }catch (InterruptedException e) {

    // TODO: handle exception

    }

    System.out.println("线程"+Thread.currentThread().getName()+"执行完毕");

    }

    }

    }

    输出结果:

    dc5410efef8cc0fa52f886f7cd8cfa84.png

    可以看出,当调用thread1.join()方法后,main线程会进入等待,然后等待thread1执行完之后再继续执行。

    实际上调用join方法是调用了Object的wait方法,这个可以通过查看源码得知:

    539137458855714488733a0c67dce938.png

    wait方法会让线程进入阻塞状态,并且会释放线程占有的锁,并交出CPU执行权限。

    由于wait方法会让线程释放对象锁,所以join方法同样会让线程释放对一个对象持有的锁。具体的wait方法使用在后面文章中给出。

    6)interrupt方法

    interrupt,顾名思义,即中断的意思。单独调用interrupt方法可以使得处于阻塞状态的线程抛出一个异常,也就说,它可以用来中断一个正处于阻塞状态的线程;另外,通过interrupt方法和isInterrupted()方法来停止正在运行的线程。

    下面看一个例子:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    public class Test {

    public static void main(String[] args)throwsIOException  {

    Test test =new Test();

    MyThread thread = test.new MyThread();

    thread.start();

    try {

    Thread.currentThread().sleep(2000);

    }catch (InterruptedException e) {

    }

    thread.interrupt();

    }

    class MyThreadextends Thread{

    @Override

    public void run() {

    try {

    System.out.println("进入睡眠状态");

    Thread.currentThread().sleep(10000);

    System.out.println("睡眠完毕");

    }catch (InterruptedException e) {

    System.out.println("得到中断异常");

    }

    System.out.println("run方法执行完毕");

    }

    }

    }

    输出结果:

    2d5bef5bd19683044c94fe24b03721ab.png

    从这里可以看出,通过interrupt方法可以中断处于阻塞状态的线程。那么能不能中断处于非阻塞状态的线程呢?看下面这个例子:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    public class Test {

    public static void main(String[] args)throwsIOException  {

    Test test =new Test();

    MyThread thread = test.new MyThread();

    thread.start();

    try {

    Thread.currentThread().sleep(2000);

    }catch (InterruptedException e) {

    }

    thread.interrupt();

    }

    class MyThreadextends Thread{

    @Override

    public void run() {

    int i =0;

    while(i

    System.out.println(i+" while循环");

    i++;

    }

    }

    }

    }

    运行该程序会发现,while循环会一直运行直到变量i的值超出Integer.MAX_VALUE。所以说直接调用interrupt方法不能中断正在运行中的线程。

    但是如果配合isInterrupted()能够中断正在运行的线程,因为调用interrupt方法相当于将中断标志位置为true,那么可以通过调用isInterrupted()判断中断标志是否被置位来中断线程的执行。比如下面这段代码:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    public class Test {

    public static void main(String[] args)throwsIOException  {

    Test test =new Test();

    MyThread thread = test.new MyThread();

    thread.start();

    try {

    Thread.currentThread().sleep(2000);

    }catch (InterruptedException e) {

    }

    thread.interrupt();

    }

    class MyThreadextends Thread{

    @Override

    public void run() {

    int i =0;

    while(!isInterrupted() && i

    System.out.println(i+" while循环");

    i++;

    }

    }

    }

    }

    运行会发现,打印若干个值之后,while循环就停止打印了。

    但是一般情况下不建议通过这种方式来中断线程,一般会在MyThread类中增加一个属性 isStop来标志是否结束while循环,然后再在while循环中判断isStop的值。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    class MyThreadextends Thread{

    private volatile boolean isStop =false;

    @Override

    public void run() {

    int i =0;

    while(!isStop){

    i++;

    }

    }

    public void setStop(boolean stop){

    this.isStop = stop;

    }

    }

    那么就可以在外面通过调用setStop方法来终止while循环。

    7)interrupted方法

    interrupted()函数是Thread静态方法,用来检测当前线程的interrupt状态,检测完成后,状态清空。通过下面的interrupted源码我们能够知道,此方法首先调用isInterrupted方法,而isInterrupted方法是一个重载的native方法private native boolean isInterrupted(boolean ClearInterrupted) 通过方法的注释能够知道,用来测试线程是否已经中断,参数用来决定是否重置中断标志。

    public static boolean interrupted() {

    return currentThread().isInterrupted(true);

    }

    public boolean isInterrupted() {

    return isInterrupted(false);

    }

    /**

    * Tests if some Thread has been interrupted. The interrupted state

    * is reset or not based on the value of ClearInterrupted that is

    * passed.

    */

    private native boolean isInterrupted(boolean ClearInterrupted);

    8)stop方法

    stop方法已经是一个废弃的方法,它是一个不安全的方法。因为调用stop方法会直接终止run方法的调用,并且会抛出一个ThreadDeath错误,如果线程持有某个对象锁的话,会完全释放锁,导致对象状态不一致。所以stop方法基本是不会被用到的。

    9)destroy方法

    destroy方法也是废弃的方法。基本不会被使用到。

    以下是关系到线程属性的几个方法:

    1)getId

    用来得到线程ID

    2)getName和setName

    用来得到或者设置线程名称。

    3)getPriority和setPriority

    用来获取和设置线程优先级。

    4)setDaemon和isDaemon

    用来设置线程是否成为守护线程和判断线程是否是守护线程。

    守护线程和用户线程的区别在于:守护线程依赖于创建它的线程,而用户线程则不依赖。举个简单的例子:如果在main线程中创建了一个守护线程,当main方法运行完毕之后,守护线程也会随着消亡。而用户线程则不会,用户线程会一直运行直到其运行完毕。在JVM中,像垃圾收集器线程就是守护线程。

    Thread类有一个比较常用的静态方法currentThread()用来获取当前线程。

    在上面已经说到了Thread类中的大部分方法,那么Thread类中的方法调用到底会引起线程状态发生怎样的变化呢?下面一幅图就是在上面的图上进行改进而来的:

    77e65e17aec7aee59a6427973ab25e96.png

    参考文章:

    展开全文
  • Thread 部分常用方法详解

    千次阅读 2020-09-29 23:25:21
    currentThread() 方法用来返回代码段正在被哪个线程调用,它是 Thread 提供的一个 native 方法,返回一个 Thread 的实例对象,源码如下: public static native Thread currentThread(); 废话就不多说了,直接...

    currentThread()

    currentThread() 方法用来返回代码段正在被哪个线程调用,它是 Thread 类提供的一个 native 方法,返回一个 Thread 类的实例对象,源码如下:

    public static native Thread currentThread();
    

    废话就不多说了,直接上代码:

    public class Run {
        public static void main(String[] args) {
            MyRunnable myRunnable = new MyRunnable();
            // 第二个参数为线程的名字
            Thread thread = new Thread(myRunnable, "Thread-itming");
            thread.start();
        }
    }
    
    class MyRunnable implements Runnable {
        public MyRunnable() {
            System.out.println("调用构造方法的线程:" + Thread.currentThread().getName());
        }
    
        @Override
        public void run() {
            System.out.println("调用 run() 方法的线程:" + Thread.currentThread().getName());
        }
    }
    

    控制台输出如下:

    调用构造方法的线程:main
    调用 run() 方法的线程:Thread-itming
    

    从输出结果可以看到,调用构造方法的线程是 main 线程,即主线程,调用 run() 方法的线程是新创建的线程 Thread-itming。

    在调用 start() 方法之前,所有的代码都是由主线程调用执行的,而在调用 start() 方法之后才会开启一个新的线程,并执行 run() 方法。

    这里我们可以思考一个问题,调用 run() 方法和 start() 方法的区别是什么?

    • 调用 run() 方法:不启动新线程,立即执行 run() 方法。
    • 调用 start() 方法:启动新的线程,然后由新线程调用 run() 方法。

    为了验证这一点,我对上面的代码做了一些小调整,代码如下:

    public class Run {
        public static void main(String[] args) {
            MyRunnable myRunnable = new MyRunnable();
            // 第二个参数为线程的名字
            Thread thread = new Thread(myRunnable, "Thread-itming");
            // thread.start();
            thread.run();
        }
    }
    
    class MyRunnable implements Runnable {
        public MyRunnable() {
            System.out.println("调用构造方法的线程:" + Thread.currentThread().getName());
        }
    
        @Override
        public void run() {
            System.out.println("调用 run() 方法的线程:" + Thread.currentThread().getName());
        }
    }
    

    控制台输出如下:

    调用构造方法的线程:main
    调用 run() 方法的线程:main
    

    从输出结果可以看到,调用构造方法和 run() 方法的线程都是 main 线程,由此可以证明直接调用 run() 方法不会启动新线程,需要调用 start() 方法才会启动新的线程。

    isAlive()

    isAlive() 方法用来判断当前线程是否处于存活状态,存活状态指的是线程已经启动且尚未终止的状态。

    下面我们来写一个案例进行测试,代码如下:

    public class Run {
        public static void main(String[] args) throws InterruptedException {
            MyThread myThread = new MyThread();
            System.out.println("begin = " + myThread.isAlive());
            myThread.start();
            System.out.println("end = " + myThread.isAlive());
        }
    }
    
    class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println("run = " + this.isAlive());
        }
    }
    

    控制台输出如下:

    begin = false
    end = true
    run = true
    

    这里我们需要注意一点,对于代码:

    System.out.println("end = " + myThread.isAlive());
    

    其输出值是不确定的(虽然不确定,但大概率返回 true),输出 true 或 false 取决于执行该行代码时 myThread 线程是否执行完毕,未执行完毕的话就返回 false,执行完毕的话就返回 true。

    我们可以代码进行一些修改,让该行代码大概率输出 false,代码如下:

    package t004;
    
    public class Run {
        public static void main(String[] args) throws InterruptedException {
            MyThread myThread = new MyThread();
            System.out.println("begin = " + myThread.isAlive());
            myThread.start();
            /**
             * 让当前线程休眠 1000 毫秒,这里的当前线程指的是 main 线程
             * 在这 1000 毫秒内,myThread 线程大概率已经执行完毕
             */
            Thread.sleep(1000);
            System.out.println("end = " + myThread.isAlive());
        }
    }
    
    class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println("run = " + this.isAlive());
        }
    }
    

    控制台输出如下:

    begin = false
    run = true
    end = false
    

    sleep()

    sleep() 方法可以让当前线程进入超时等待状态(TIME_WAITING),并在指定时间后恢复到运行状态(RUNNABLE)。它有两个重载的方法,部分源码如下:

    public static native void sleep(long millis) throws InterruptedException
    
    public static void sleep(long millis, int nanos) throws InterruptedException
    

    sleep(long millis):参数 millis 的单位是毫秒。

    sleep(long millis, int nanos):参数 millis 的单位是毫秒,参数 nanos 的单位是纳秒,线程等待的时间是两个参数的和。

    getId()

    getId() 方法用于获取线程的唯一标识。

    下面通过一个示例进行说明,代码如下:

    public class Test {
        public static void main(String[] args) {
            Thread thread = Thread.currentThread();
            System.out.println(thread.getName() + " " + thread.getId());
        }
    }
    

    控制台输出如下:

    main 1
    

    yield()

    yield() 方法的作用是让当前线程释放 CPU 资源,并且当前线程会从运行中状态变为就绪状态(在 Java 中,运行中状态和就绪状态都属于运行状态),然后等待系统调度。

    举个例子:有一群小朋友排队等待荡秋千,此时正在荡秋千的甲忽然说我愿意让出秋千,然后我们再一起竞争。最后的结果可能是其他小朋友获得了荡秋千的机会,也可能依然是甲获得了荡秋千的机会。

    下面我们来编写一段代码,测试一下 yield() 方法的使用效果,代码如下:

    public class Run {
        public static void main(String[] args) {
            Thread thread = new Thread() {
                @Override
                public void run() {
                    long beginTime = System.currentTimeMillis();
                    long count = 0;
                    for (int i = 0; i < 100000000; i++) {
                        // Thread.yield();
                        count = count + i;
                    }
                    long endTime = System.currentTimeMillis();
                    System.out.println("耗时 " + (endTime - beginTime) + " 毫秒");
                }
            };
            thread.start();
        }
    }
    

    控制台输出如下:

    耗时 29 毫秒
    

    然后我们去掉注释,再次运行,控制台输出如下:

    耗时 11008 毫秒
    

    我们可以看到去掉注释前后这段代码运行所耗费的时间差距是非常大的,这是因为去掉注释后每一次 for 循环当前线程都会释放所占用的 CPU 资源,然后等待系统的重新调度,所以耗费的时间比较长。

    展开全文
  • Java中Thread类方法简介

    万次阅读 2018-06-05 17:37:48
    Thread t1 = new Thread(); t1.start(); 新建线程,应该调用start()方法启动线程;如果直接调用run()方法,该方法也会执行,但会被当做一个普通的方法,在当前线程中顺序执行;而如果使用start()方法,则会创建一个...
  • Thread类、Runnable接口详解

    千次阅读 2019-12-26 23:08:02
    Thread类想必都不陌生,第一次学习多线程的时候就一定会接触Thread类。本篇主要从Thread类的定义、使用、注意事项、源码等方面入手,全方位的讲解Thread类。 Thread 我们经常会被问到这样一个问题: Java开启一个新...
  • A通过调用Thread类的start()方法来启动一个线程,这时此线程是处于就绪状态,并没有运行。 B他们都可以实现了多线程运行。 Crun方法是thread的一个普通方法调用。 D调用start方法后,一旦得到cpu时间片,就...
  • Thread类中, 线程状态是通过threadStatus属性以及State枚举类实现的: /* Java thread status for tools, * initialized to indicate thread 'not yet started' */ private volatile int threadStatus = 0; ...
  • Thread类中的方法:join()、sleep()、yield()之间的区别

    万次阅读 多人点赞 2018-07-20 11:47:28
    1. Thread类中的常用方法简介 2. Join()方法 3. Sleep() 方法:不会释放锁 4. Yield()方法:线程让步 不会释放锁 1. Thread类中的常用方法简介 首先,先看一下Thread类中的常见方法: 最主要的是区分其中...
  • 我们看Thread类的定义知道,它实现了Runable接口 public class Thread implements Runnable { ... } 而Runnable接口的定义如下: @FunctionalInterface public interface Runnable { public abstract void run(); ...
  • 我们进行程序开发的时候,肯定避免不了要处理并发的情况。 一般并发的手段有采用多进程和多线程。 但线程比进程更轻量化,系统开销一般也更低,所以大家更倾向于用多线程的方式处理并发的情况。...thread...
  • 一、初识 java的线程是通过java.lang.Thread类来实现的。VM启动时会有一个由主方法所定义...通过调用Thread类的start()方法来启动一个线程。 在Java当中,线程通常都有五种状态,创建、就绪、运行、阻塞和死亡。 ...
  • 【Java】Thread类中的join()方法原理

    万次阅读 多人点赞 2018-05-09 18:34:09
    join()是Thread类的一个方法。根据jdk文档的定义: public final void join()throws InterruptedException: Waits for this thread to die. join()方法的作用,是等待这个线程结束;但显然,这样的定义并不清晰...
  • thread类中start()和run()方法的区别

    千次阅读 2019-04-12 11:08:21
    run方法体代码执行完毕而直接继续执行下面的代码: 通过调用Thread类的start()方法来启动一个线程,这时此线程是处于就绪状态,并没有运行。 然后通过此Thread类调用方法run()来完成其运行操作的,这里方法run()称为...
  • 而今天将要跟大家一起聊聊的是:并发编程的基石——Thread 的工作原理。 事实上,在笔者回忆关于 Thread 的核心 API 以及对应的线程状态转换关系时,总觉得印象有一些模糊,故此才有这篇文章。本文的核心议题是...
  • Thread类

    万次阅读 2018-03-25 15:41:09
    1 start方法 start()用来启动一个线程,当调用start方法后,系统才会开启一个新的线程来执行用户定义的子任务,在这个过程中,会为相应的线程分配需要...注意,继承Thread类必须重写run方法,在run方法中定义具体要...
  • 如果使用Thread类处理线程就方便得多了,可以直接使用Thread对象的join方法等待线程函数执行完毕再往下执行,也就是说,在主线程(main函数)中调用Thread对象的join方法,并且Thread对象的线程函数没有执行完毕,...
  • Thread类的run()和start()方法的区别

    万次阅读 2018-03-15 11:36:26
    start()方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码: 通过调用Thread类的start()方法来启动一个线程,这时此线程是处于就绪状态,并没有运行。...
  • 其作用是中断此线程(此线程不一定是当前线程,而是指调用该方法Thread实例所代表的线程),但实际上只是给线程设置一个中断标志,线程仍会继续运行。   interrupted()方法 作用是测试当前线程是否被中断...
  • 为了更好地对与线程有关的代码进行封装,可以从Thread类派生一个子类。然后将与线程有关的代码都放到这个...从Thread类继承最简单的方式是在子类的构造方法中通过super()函数调用父类的构造方法,并传入相应的参数值。
  • 当一个方法后面声明可能会抛出InterruptedException异常时,说明该方法是可能会花一点时间,但是可以取消的方法...2.Java.lang.Thread类的sleep方法。 3.Java.lang.Thread类的join方法。 这里我们只看sleep方法
  • Android ThreadthreadLoop方法

    千次阅读 2018-04-12 17:27:54
    Android Framework中的线程Thread及它的threadLoop方法 在Framework中的Thread普遍的特点就是有一个 threadLoop方法。它到底是怎么循环起来的。 Android中java世界的Thread 先来看看java是怎么创建一个线程的。...
  • 多线程中Thread的join方法

    千次阅读 2021-09-21 09:46:30
    join方法Thread类中的一个方法,该方法的定义是等待该线程执行直到终止。其实就说join方法将挂起调用线程的执行,直到被调用的对象完成它的执行。 join实例(以一道面试题为例) 现在有T1、T2、T3三个线程,你怎样...
  • Thread 的构造方法

    万次阅读 2014-07-08 19:26:28
    在Java中创建线程有两种方法:使用Thread类和使用Runnable接口。在使用Runnable接口时需要建立一个Thread实例。因此,无论是通过Thread类还是Runnable接口建立线程,都必须建立Thread类或它的子类的实例。Thread类的...
  • java Thread的start和run方法的区别

    千次阅读 多人点赞 2019-02-23 20:10:07
    一、认识Thread的 start() 和 run() 概述: t.start()会导致run()方法被调用,run()方法中的内容称为线程体,它就是这个线程需要执行的工作。 用start()来启动线程,实现了真正意义上的启动线程,此时会出现异步...
  • java之多线程中Thread类和Runnable接口使用方法

    千次阅读 多人点赞 2017-11-04 17:15:01
    java提供了两种线程方式,一种是继承java.lang包下的Thread类,覆写Thread类的run()方法,在run()方法中实现运行在线程上的代码!第二种是实现Runnable接口创建多线程。下面就跟大家具体的介绍一下这两种方式! 在...
  • 它们普遍的特点就是有一个threadLoop方法。按照字面的意思应该是这个线程能够循环处理数据。对应我想到到了java上层中的HandlerThread,这个估计也差不多,但当时心里总有一个疙瘩,想弄清楚它到底是怎么循环起来的...
  • C++多线程(一)thread类

    万次阅读 多人点赞 2018-04-10 16:28:29
    与 C++11 多线程相关的头文件地方 C++11 新标准中引入了四个头文件来支持多线程编程,他们分别是&lt;atomic&gt; ,&...:该头文主要声明了两个, std::atomic 和 std::atomic_flag...
  • 继承Thread类,重写run()方法; 实现Runnable接口,重写run()方法; 线程启动会通过调用start方法来启动线程而不能直接调用run方法。 这里就会引出两个经典的面试题: 为什么线程启动是调用start方法来启动线程而...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 397,046
精华内容 158,818
关键字:

下面哪些是thread类的方法