多线程-线程停止、线程休眠sleep()、线程礼让yield()、线程强制执行join()

372 阅读3分钟

多线程常用方法

线程停止

  • JDK提供的stop()、destroy() ->已废弃,不推荐

  • 线程自己停下来

    • 利用次数
    • 标志位

标志位示例:

public class ThreadStopDemo {

    public static void main(String[] args) throws InterruptedException {
        ThreadStop threadStop = new ThreadStop();
        new Thread(threadStop, "a").start();
        TimeUnit.SECONDS.sleep(2);
        threadStop.stop();
    }
}


class ThreadStop implements Runnable {

    private boolean flag = true;

    @Override
    public void run() {
        while(flag) {
            System.out.println(Thread.currentThread().getName() + "线程正在执行!");
        }
    }

    /**
     * 提供一个方法改变flag为false,来停止线程
     */
    public void stop() {
        this.flag = false;
        System.out.println("线程停止");
    }
}

线程休眠

sleep()方法

Thread.sleep(1000);
TimeUnit.SECONDS.sleep(1);
  • 异常抛出

  • sleep时间达到后,线程进入就绪状态

  • sleep可以模拟网络延时、倒计时

  • 每个对象都会有一把锁,sleep不会释放锁

模拟网络延时

// 模拟网络延时
public class ThreadSleep {

    /*
    1. sleep()结束后,线程进入就绪状态
    2. sleep()不会释放锁
    3. sleep()需要捕获异常
    */


    public static void main(String[] args) throws InterruptedException {
        System.out.println("开始售票");

        BuyTicketThread buyTicketThread = new BuyTicketThread();
        new Thread(buyTicketThread, "张三").start();
        new Thread(buyTicketThread, "李四").start();
        new Thread(buyTicketThread, "王五").start();
    }
}

class BuyTicketThread implements Runnable {

    private Integer ticketNum = 20;

    @Override
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException interruptedException) {
            interruptedException.printStackTrace();
        }
        while (ticketNum > 0) {
            System.out.println(Thread.currentThread().getName() + "买到第" + ticketNum-- + "张票");
        }
    }
}

线程礼让

  • 让当前正在执行的线程暂停但不阻塞
  • 将线程从运行状态转为阻塞状态
  • CPU重新调度,礼让不一定成功。

不礼让测试代码:

public class ThreadYield {

    public static void main(String[] args) throws InterruptedException {
        YieldA yieldA = new YieldA();
        YieldB yieldB = new YieldB();

        new Thread(yieldA, "A").start();
        new Thread(yieldB, "B").start();

    }

}

class YieldA implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "线程正在执行");
        System.out.println(Thread.currentThread().getName() + "线程结束执行");
    }
}

class YieldB implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "线程正在执行");
        System.out.println(Thread.currentThread().getName() + "线程结束执行");
    }
}

输出结果: image.png

线程礼让测试:

class YieldA implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "线程正在执行");
        Thread.yield();
        System.out.println(Thread.currentThread().getName() + "线程结束执行");
    }
}

class YieldB implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "线程正在执行");
        System.out.println(Thread.currentThread().getName() + "线程结束执行");
    }
}

输出结果:
线程礼让成功 image.png

线程强制执行-Join

thread.join() 强制执行thread,当thread执行结束后,其他线程其继续执行。

(插队)

正常的多线程测试:

public class ThreadJoin implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 50; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }

    public static void main(String[] args) {

        Runnable target;
        Thread thread = new Thread(new ThreadJoin(), "A");
        thread.start();

        for (int i = 0; i < 100; i++) {
            System.out.println("主线程:" + i);
        }
    }
}

执行结果:

主线程:0
主线程:1
主线程:2
主线程:3
主线程:4
A:0
主线程:5
主线程:6
主线程:7
主线程:8
主线程:9
主线程:10
主线程:11
主线程:12
A:1
主线程:13
主线程:14
主线程:15
主线程:16
主线程:17
A:2
主线程:18
A:3
主线程:19
A:4
主线程:20
主线程:21
A:5
  ... ...

可以看到线程A与主线程交替执行。

在主线程中添加代码thread.join();

public class ThreadJoin implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 50; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }

    public static void main(String[] args) throws InterruptedException {

        Runnable target;
        Thread thread = new Thread(new ThreadJoin(), "A");
        thread.start();

        for (int i = 0; i < 100; i++) {
            if (i == 20) {
                thread.join();
            }
            System.out.println("主线程:" + i);
        }
    }
}

执行结果:

主线程:1
主线程:2
主线程:3
主线程:4
主线程:5
主线程:6
主线程:7
A:0
A:1
A:2
A:3
A:4
A:5
A:6
主线程:8
主线程:9 
... ...
// i == 20
主线程:19
A:10
A:11
A:12
... ...
A:48
A:49

在i==20之前,线程A与main线程交替执行,当i==20是,强制A线程执行结束。