Thread类的一些用法

在Java中,Thread类是一个实现多线程编程的一个基础类。我们可以对线程有多种操作,比如创建线程,终止线程,休眠线程,等待线程,获取线程的实例等。下面将逐个介绍以上操作。

1. 创建线程

创建线程有多种方法,主要有:(1)继承Thread类,重写run方法;(2)实现Runnable,重写run方法;(3)继承Thread,重写run,使用匿名内部类;(4)实现Runnable,重写run,使用匿名内部类;(5)使用Lambda表达式(最常用)

1.1 继承Thread,重写run()

public class MyThread1 extends Thread{
    //继承Thread,重写run

    @Override
    public void run(){

            System.out.println("this is thread!");
        
    }

    public static void main(String[] args) throws InterruptedException {
        Thread t = new MyThread1();

        t.start();//调用了系统的API,在系统内部创建了新的线程,这个线程会调用Thread类中的run方法,实现了并发编程
        
        System.out.println("this is main!");
        
    }
}

1.2  实现Runnable,重写run()

public class MyThread2 implements Runnable{
    @Override
    public void run() {
            System.out.println("this is thread!");
    }
    
    public static void main(String[] args){
        //实现runnable,重写run
            Runnable runnable = new MyThread2();
            Thread t = new Thread(runnable);
            t.start();
            System.out.println("this is main!");
    }
}

1.3 继承Thread,重写run(),使用匿名内部类

public class MyThread3 extends Thread{
    //继承Thread,重写run,使用匿名内部类
    public static void main(String[] args) {
        Thread t = new MyThread3(){
            @Override
            public void run() {
                    System.out.println("this is thread!");
            }
        };
            t.start();
            System.out.println("this is main!");
    }
}

1.4 实现Runnable,重写run(),使用匿名内部类

public class MyThread4{
    public static void main(String[] args) {
        //实现runnable,重写run,使用匿名内部类
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                    System.out.println("this is thread!");
            }
        };
        Thread t = new Thread(runnable);
        t.start();
            System.out.println("this is main!");
    }
}

1.5 使用Lambda表达式

public class MyThread5 {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            System.out.println("this is thread!");
        });
        t.start();
        System.out.println("this is main!");
    }
}

以上是五种创建线程的方式,start()是线程的入口方法t.start()调用了系统的API,在系统中创建了一个新的线程,这个线程会调用Thread的run()方法,实现了并发编程,能交替执行主线程和t线程中的输出内容。

9c67a688d0a043289e42a869c276316a.png

【t.start()和t.run()的区别】 

若将t.start()更换为t.run(),t.run()不会调用系统的API,也就不会创建新的线程,因此t.run()无法实现并发编程,只能一个线程一个线程的运行,只有当前线程运行完毕后才能去执行其他线程任务。

public class MyThread5 {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            while (true){
                System.out.println("this is thread!");
            }
        });
        t.run();
        //t.start();
        while (true){
            System.out.println("this is main!");
        }
    }
}

ab3b094e08fb4de7b4bae173a654f6ad.png

运行结果是无限循环输出 this is thread!

每个线程是一个独立的执行流t.start()可以实现并发编程,能交替运行两个线程,即能交替输出两个线程的输出内容。

public class MyThread5 {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            while (true){
                System.out.println("this is thread!");
            }
        });
        //t.run();
        t.start();
        while (true){
            System.out.println("this is main!");
        }
    }
}

23a7c74b20da40618dcc7bde0efd7080.png

2. 休眠线程 和 等待线程

2.1 休眠线程

可以使用Thread类的sleep(毫秒)方法,来使一个线程休眠一定的时间,时间到之后,该线程就能继续被调度执行了 

public class Demo3 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            System.out.println("t线程执行中!");

        });
        t.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("执行完毕");
    }
}

8e42725e55c34a95a185638ab8669b19.png

2.2 等待线程

使用Thread类的无参版本的join()方法,可让 某一个线程 等待 另一个线程执行结束后再执行,该方法也就控制着线程的执行结束的顺序

在哪个线程中调用了join方法,则哪个线程就等待另一个线程先执行。比如 在main中调用t.jion(),则main线程就等待t线程先执行。

代码示例如下:

public class Demo3 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            System.out.println("t线程执行中!");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        t.start();
        t.join();
        System.out.println("main线程执行中");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("执行完毕");
    }
}

e9a8267e0ec5493b9a691037cba3b312.png

这样就可以控制线程的结束顺序,一个线程等待另一个线程执行结束后再执行。

由于线程调度是随机的,且创建一个新的线程有一定系统开销,若不使用join方法,就会先去执行main线程的任务了。

df51048dfc304adb80385eb4a0075eaa.png

3. 终止线程 和 获取线程实例

Thread内部有一个标志位,该标志位就是用来判定当前线程是否结束,t.interrupt()就可将t线程内部的标志位设置为true,这样就可以终止t线程. 代码如下:

其中,Thread.currentThread()是用来获取当前线程的实例

哪个线程调用了Thread.currentThread(),就返回哪个线程的对象如下面代码中,在t线程中调用了Thread.currentThread(),则Thread.currentThread()就返回t线程的对象,也就是t。因此while循环条件的代码中Thread.currentThread()就获取到了当前线程的对象t。

【终止一个线程的两步操作】:

  (1) 主线程main中 t.interrupt(),此操作就将t线程中的标志位设置为true

  (2) Thread.currentThread().isInterrupted(),此操作用来判定当前线程是否终止

  以上两步操作就成功将t线程终止了。

public class Demo2 {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()){
                System.out.println("t线程工作中!");
            }
        });
        t.start();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        
        t.interrupt();
        System.out.println("成功终止t线程!");
    }
}

ab7db94266874b309000cd0327d4115e.png 

若t线程中有sleep()方法,如以下代码,t.interrupt()会触发sleep内部中的一个异常,且会重置线程内部的标志位,即将刚刚设置的标志位true还原为false,这样线程就不会终止了(catch到的是e.printStackTrace()基础上)。这样的话即使调用了t.interrupt(),t线程也不会终止。这种情况就是将主动权交给我们自己,若确定要终止线程,就在catch中加上 break,就可终止t线程了。

public class Demo2 {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()){
                System.out.println("t线程工作中!");
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                   //throw RuntimeException(e);
                    e.printStackTrace();
                    //break;
                }
            }
        });
        t.start();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        t.interrupt();
        System.out.println("成功终止t线程!");
    }
}

 8af7c2120c614eb5a91d3b7e64f2d22b.png

若catch中是throw RuntimeException(e),则会抛出运行时异常,不用加break,线程也由于异常而终止了。

1535e6b0de354c458e8deaf00cb13725.png

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值