12 线程休眠 sleep,线程礼让 yield, Thread.join()的使用,线程过期的suspend()、resume()和stop()

Java多线程常用方法,过期方法

    • 线程休眠 sleep
    • 线程礼让 yield
    • Thread.join()的使用
    • 线程过期的suspend()、resume()和stop()

线程休眠 sleep

  • sleep(long)指定当前线程阻塞的毫秒数
  • sleep存在异常InterruptException
  • sleep时间达到后线程进入就绪状态
  • sleep可以模拟网络延时
  • 每个对象都有一把锁,sleep不会释放锁

线程礼让 yield

yield() 暂停当前线程,使当前线程从running状态变为Ready状态,

让cpu重新调度。至于cpu选中那个线程执行是随机的,完全取决于cpu调度。

public class ThreadYield {
    public static void main(String[] args) {
        MyYield myYield = new MyYield();
        new Thread(myYield,"A").start();
        new Thread(myYield,"B").start();

    }
}

class MyYield implements Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " start...");
        Thread.yield();
        System.out.println(Thread.currentThread().getName() + " stop...");
    }
}

执行结果

多执行几次,会发现不一样的结果

A start...
B start...
A stop...
B stop...

Thread.join()的使用

一个线程A执行了B.join()时,当前线程A等待B线程终止之后才执行线程A剩下部分。

join()保证线程B的可见性,即线程B中修改的变量,线程A可见。

/**
 * Thread join方法
 */
public class Join {
    public static void main(String[] args) throws Exception {
        Thread previous = Thread.currentThread();
        for (int i = 0; i < 10; i++) {
            // 每个线程拥有前一个线程的引用,需要等待前一个线程终止,才能从等待中返回
            Thread thread = new Thread(new Domino(previous), String.valueOf(i));
            thread.start();
            previous = thread;
        }
        TimeUnit.SECONDS.sleep(5);
        System.out.println(Thread.currentThread().getName() + " terminate.");
    }

    static class Domino implements Runnable {
        private Thread thread;

        public Domino(Thread thread) {
            this.thread = thread;
        }

        public void run() {
            try {
                thread.join();
            } catch (InterruptedException e) {
            }
            System.out.println(Thread.currentThread().getName() + " terminate.");
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}
main terminate.
0 terminate.
1 terminate.
2 terminate.
3 terminate.
4 terminate.
5 terminate.
6 terminate.
7 terminate.
8 terminate.
9 terminate.

Process finished with exit code 0

每个线程终止的前提是前驱线程的终止,每个线程等待前驱线程 终止后,才从join()方法返回。

join方法相当于插队执行,最早插队的是main,依次为0-9,故执行顺序如上。

a.join()方法,等待a线程执行完毕,再执行其他线程,其他线程阻塞

public class ThreadJoin {

    public static void main(String[] args) throws InterruptedException {
        MyJoin myJoin = new MyJoin();

        Thread t1 = new Thread(myJoin, "张三");
        t1.start();

        for (int i = 0; i < 200; i++) {
            Thread.sleep(50);
            System.out.println("王五 执行到 " + i);
            if (i==100){
                t1.join();
            }
        }

    }

}

class MyJoin implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+" 执行到 " + i);
        }
    }
}

线程过期的suspend()、resume()和stop()

暂停 suspend()

恢复 resume()

停止 stop()

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * 过期的方法
 * 暂停 suspend()
 * 恢复 resume()
 * 恢复 stop()
 * 像音乐播放器的按键一样
 */
public class Deprecated {
    public static void main(String[] args) throws Exception {
        DateFormat format = new SimpleDateFormat("HH:mm:ss");
        Thread printThread = new Thread(new Runner(), "PrintThread");
        printThread.setDaemon(true);
        printThread.start();
        TimeUnit.SECONDS.sleep(3);
        // 将PrintThread进行暂停,输出内容工作停止
        printThread.suspend();
        System.out.println("main suspend PrintThread at " + format.format(new Date()));
        TimeUnit.SECONDS.sleep(3);
        // 将PrintThread进行恢复,输出内容继续
        printThread.resume();
        System.out.println("main resume PrintThread at " + format.format(new Date()));
        TimeUnit.SECONDS.sleep(3);
        // 将PrintThread进行终止,输出内容停止
        printThread.stop();
        System.out.println("main stop PrintThread at " + format.format(new Date()));
        TimeUnit.SECONDS.sleep(3);
    }

    static class Runner implements Runnable {
        @Override
        public void run() {
            DateFormat format = new SimpleDateFormat("HH:mm:ss");
            while (true) {
                System.out.println(Thread.currentThread().getName() + " Run at " +
                        format.format(new Date()));
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}
//执行结果
PrintThread Run at 21:30:27
PrintThread Run at 21:30:28
PrintThread Run at 21:30:29
main suspend PrintThread at 21:30:30
PrintThread Run at 21:30:33
main resume PrintThread at 21:30:33
PrintThread Run at 21:30:34
PrintThread Run at 21:30:35
main stop PrintThread at 21:30:36

Process finished with exit code 0

不建议使用的原因主要有:以suspend()方法为例,在调用后,线程不会释放已经占有的资源(比如锁),而是占有着资源进入睡眠状态,这样容易引发死锁问题。同样,stop()方法在终结 一个线程时不会保证线程的资源正常释放,通常是没有给予线程完成资源释放工作的机会,因此会导致程序可能工作在不确定状态下。

你可能感兴趣的:(Java,Thread,ThreadPool,线程休眠,sleep,线程礼让,yield,线程插队join,线程过期方法,Java多线程方法)