JavaSE多线程《三》

57 篇文章 0 订阅
7 篇文章 0 订阅

往期回顾:

JavaSE多线程《一》

JavaSE多线程《二》

3.5 线程停止
多线程中有三种方式可以停止线程。

  1. 设置标记位,可以使线程正常退出。

  2. 使用stop方法强制使线程退出,但是该方法不太安全所以已经被废弃了。

  3. 使用Thread类中的一个 interrupt() 可以中断线程。

首先示例,利用设置标记为flag 使线程停止:

代码如下:

package com.revision.Thread;

class TestFlagStop implements Runnable {

    private boolean flag = true;

    @Override
    public void run() {
        int i = 1;
        while (flag) {
            try {
                Thread.sleep(1000);
                System.out.println("第" + i + "次执行程序,线程名为" + Thread.currentThread().getName());
                i++;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}

public class FlagStop {

    public static void main(String[] args) throws InterruptedException {
        TestFlagStop tfs = new TestFlagStop();
        Thread thread = new Thread(tfs,"子线程A");
        thread.start();
        Thread.sleep(2000);
        tfs.setFlag(false);
        System.out.println("代码结束!");
    }

}

运行结果如下:

在这里插入图片描述

使用stop终止线程:
代码如下:

MyThread myThread = new MyThread();
Thread thread1 = new Thread(myThread,"子线程A");
thread1.start();
Thread.sleep(3000);
thread1.stop();
System.out.println("代码结束");

使用stop方法强制使线程退出,但是该方法不太安全所以已经被废弃了。

为什么说不安全呢?因为stop会解除由线程获取的所有锁定,当在一个线程对象上调用stop()方法时,这个线程对象所运行的线程就会立即停止,假如一个线程正在执行:synchronized void { x = 3; y = 4;} 由于方法是同步的,多个线程访问时总能保证x,y被同时赋值,而如果一个线程正在执行到x = 3;时,被调用了 stop()方法,即使在同步块中,它也会马上stop了,这样就产生了不完整的残废数据

利用interrupt 方法实现线程的停止:
代码如下

package com.revision.Thread;

class TestThread implements Runnable{

    private boolean flag = true;

    @Override
    public void run() {
        int i = 0;
        while(flag){
            try {
                Thread.sleep(1000);
                boolean bool = Thread.currentThread().isInterrupted();
                if(bool){
                    System.out.println("非阻塞情况下执行该操作:  线程状态" + bool);
                    break;
                }
                System.out.println("第" + i + "次执行,线程名称" + Thread.currentThread().getName());
                i++;
            } catch (InterruptedException e) {
                System.out.println("退出了");
                boolean bool = Thread.currentThread().isInterrupted();
                System.out.println(bool);
                return;
            }
        }
    }
    public void setFlag(boolean flag){
        this.flag = flag;
    }
}

public class TestInterrupt {

    public static void main(String[] args) throws InterruptedException {
        TestThread tt = new TestThread();
        Thread t1 = new Thread(tt,"子线程A");
        t1.start();
        Thread.sleep(10000);
        t1.interrupt();
        System.out.println("代码结束!");
    }

}

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

interrupt() 方法只是改变中断状态而已,它不会中断一个正在运行的线程。这一方法实际完成的是,给受阻塞的线程发出一个中断信号,这样受阻线程就得以退出阻塞的状态。
然而interrupt()方法并不会立即执行中断操作;具体而言,这个方法只会给线程设置一个为true的中断标志(中断标志只是一个布尔类型的变量),而设置之后,则根据线程当前的状态进行不同的后续操作。如果,线程的当前状态处于非阻塞状态,那么仅仅是线程的中断标志被修改为true而已;如果线程的当前状态处于阻塞状态,那么在将中断标志设置为true后,还会有如下三种情况之一的操作:
如果是wait、sleep以及join三个方法引起的阻塞,那么会将线程的中断标志重新设置为false,并抛出一个
InterruptedException
如果在中断时,线程正处于非阻塞状态,则将中断标志修改为true,而在此基础上,一旦进入阻塞状态,则按照阻塞状态的情况来进行处理;例如,一个线程在运行状态中,其中断标志被设置为true之后,一旦线程调用了wait、join、sleep方法中的一种,立马抛出一个InterruptedException,且中断标志被程序会自动清除,重新设置为false。
通过上面的分析,我们可以总结,调用线程类的interrupt方法,其本质只是设置该线程的中断标志,将中断标志设置为true,并根据线程状态决定是否抛出异常。因此,通过interrupted方法真正实现线程的中断原理是:开发人员根据中断标志的具体值,来决定如何退出线程

3.6 线程优先级

线程的优先级指的是,线程的优先级越高越有可能先执行,但仅仅是有可能而已

在Thread类中提供有如下优先级方法:
·设置优先级

public final void setPriority(int newPriority)

·取得优先级

public final int getPriority()

对于优先级设置的内容可以通过Thread类的几个常量来决定

1. 最高优先级:public final static int MAX_PRIORITY = 10;
2. 中等优先级:public final static int NORM_PRIORITY = 5;
3. 最低优先级:public final static int MIN_PRIORITY = 1;

代码示例:

package com.revision.Thread;


class TestSetPriority implements Runnable{
    @Override
    public void run() {
        for(int i = 0;i < 5; i++){
            System.out.println("当前线程:" + Thread.currentThread().getName() + " i = "+ i);
        }
    }
}

public class SetPriority {
    public static void main(String[] args) {
        TestSetPriority tsp = new TestSetPriority();
        Thread t1 = new Thread(tsp,"子线程A");
        Thread t2 = new Thread(tsp,"子线程B");
        Thread t3 = new Thread(tsp,"子线程C");
        t1.setPriority(Thread.MAX_PRIORITY);
        t2.setPriority(Thread.MIN_PRIORITY);
        t3.setPriority(Thread.MIN_PRIORITY);
        t1.start();
        t2.start();
        t3.start();
    }
}

运行结果为:
在这里插入图片描述
可见:A的优先级最高,最先执行完,其次时B和C交替执行,因为他俩的优先级相等。

思考:
主方法也是个线程,那么它的优先级时多少呢?

public class TestDemo {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getPriority());
}
}

结果为 中等优先级

再来分析一个问题:
比如,在A线程中启动B线程,他们的优先级是如何的?

下面我们来观察一下线程的继承性:

package com.revision.Thread;

class A implements  Runnable{
    @Override
    public void run() {
        System.out.println("A的优先级为:" + Thread.currentThread().getPriority());
        Thread thread = new Thread(new B());
        thread.start();
    }
}

class B implements Runnable{
    @Override
    public void run() {
        System.out.println("B的优先级为:" + Thread.currentThread().getPriority());
    }
}

public class ThreadExtends {
    public static void main(String[] args) {
        Thread thread = new Thread(new A());
        thread.setPriority(Thread.MAX_PRIORITY);
        thread.start();
    }
}

运行结果如下:
在这里插入图片描述
可以看到,我们在A线程执行时,new了一个新线程B,此时B也获得了和A一样的优先级,最高优先级。

这就是多线程优先级的继承特性。也就是在A线程中创造出来的线程B的优先级和A线程完全一致。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值