Thread类的基本用法

目录

一,线程创建

1.1 继承Thread类,重写run方法

1.2 实现Runnable接口,重写run方法

1.3 使用匿名内部类,继承Thread

1.4 使用匿名内部类,实现Runnable接口

1.5 使用lambda表达式

 ​编辑

二,线程中断

 三,线程等待

四,线程休眠


一,线程创建

线程的创建一共有五种方法.接下来我将一一演示.

1.1 继承Thread类,重写run方法

public class ThreadDemo4 {
    public static void main(String[] args) {
        Thread t = new MyThread();
        t.start();
    }
}
class MyThread extends Thread{
    @Override
    public void run() {
        System.out.println("MyThread");
    }
}

这就是继承Thread类,重写run方法来创建线程的方法.其实就是创建了一个新的类,继承Thread,然后重写方法即可.

1.2 实现Runnable接口,重写run方法

public class ThreadDemo5 {
    public static void main(String[] args) {
        Mythread2 myThread = new Mythread2();
        Thread t = new Thread(myThread);
        t.start();
    }
}
class Mythread2 implements Runnable{
    @Override
    public void run() {
        System.out.println("Mythread");
    }
}

这个其实就是,创建一个类来实现Runnable接口中的run方法.然后创建一个Mythread对象,将Mythread对象传入Thread的构造方法中去,这种方法不推荐使用,使用起来比较繁琐. 

1.3 使用匿名内部类,继承Thread

public class ThreadDemo6 {
    public static void main(String[] args) {
        Thread t = new Thread(){
            @Override
            public void run() {
                System.out.println("Thread");
            }
        };
        t.start();
    }
}

 这个是使用匿名内部类来继承Thread类的方法,实际上和第一种的方法没有本质区别.

1.4 使用匿名内部类,实现Runnable接口

public class ThreadDemo7 {
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Thread");
            }
        });
        t.start();
    }
}

这个方法也是用了匿名内部类的形式,来实现了Runnable接口.很简单,没有什么好说的.

1.5 使用lambda表达式

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

 

使用lambda表达式这个方法最简单,是推荐使用的.实际上就是在()中使用lambda实现run方法.

二,线程中断

在线程里,我们有的时候想要让一个线程中断.这时候我们就可以使用interrupt这个方法.来通知线程中断.

代码如下:

public class ThreadDemo8 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(()->{
            while(!Thread.currentThread().isInterrupted()){
               System.out.println("Thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        t.start();
        Thread.sleep(3000);
        t.interrupt();
    }
}

 

我们看上述代码,首先我们创建了一个线程,其中run方法中的while的判断条件是 !Thread.currentThread().isInterrupted().其中,Thread.currentThread()这个方法是用来获取到当前线程的引用对象.哪个线程调用它,就可以获取到哪个线程的对象引用.而 isInterrupted这个方法是用来判断线程是否被终止的.在while内部,我们看到每隔一秒就打印一个Thread.

在main中,t.start创建了线程.然后让main线程睡3秒钟.接着调用t.interrupt方法来通知线程终止.

但是我们看到的结果却不尽如人意,我们希望我们在调用t.interrupt方法之后,线程就终止不再打印Thread了.但是我们看到,在报了一个异常之后,我们的线程并没有终止,而是继续打印了Thread,这是怎么回事?

在调用interrupt的时候,会把线程内部的标志位设置成true,并且当线程如果正在进行sleep,就会触发异常,把sleep唤醒.但是在唤醒sleep的时候,还会做一件事,就是把刚才设置的标志位再设置成false(清空了标志位).这就导致了在catch了sleep的异常之后,线程还在继续执行.

这样就导致了,在调用了interrupt方法之后,只是通知t线程你要终止了.但是终不终止,在于t.你通知了,我不一定要遵守呗.因此,啥时候要结束这个线程,都是由自己线程内部自身的代码来决定的.主动权就交到了程序员的手里.

注意:1.当线程在sleep中休眠的时候,此时调用interrupt会把t线程唤醒.此时interrupt方法就触发了sleep中的异常.导致sleep提前返回.

        2. interrupt会使标志位为true.
        3.sleep被唤醒的时候,会把线程的标志位清空.

那我们该如何去控制线程的结束呢?

1) 主动跳出循环(加break)

如果在上述代码中加上一个break(如图),那么就可以主动跳出循环.

2) 稍后进行终止

 三,线程等待

当我们想让一个线程等待另一个线程执行结束,那么我们就可以使用join来进行操作.

代码如下:

public class ThreadDemo9 {
    public static void main(String[] args) {
        Thread t = new Thread(()->{
           for(int i = 0;i<3;i++){
               System.out.println("Thread");
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   throw new RuntimeException(e);
               }
           }
        });
        t.start();
        System.out.println("join之前");
        //此处的join可以使当前的main线程来等待t线程执行结束.
        try {
            t.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        System.out.println("join之后");
    }
}

 

本来执行完start之后,t线程和main线程就会并发执行,分头行动,main和t都往下执行.但是当我们使用了join,那么main线程就发生了阻塞,main线程就会一直阻塞到线程执行结束,main线程才会从join中恢复,才能继续往下执行.

此时main线程是一直等到t线程彻底执行完毕之后才继续往下执行,否则就不执行,这叫做死等.

 在join()里面,也可以给定参数,指定一个最大等待时间.

四,线程休眠

线程休眠就是利用sleep方法,来使线程进行固定时间的休眠,此时线程处于TIMED_WAITING状态.

代码如下:

public class ThreadDemo10 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(()->{
           for(int i = 0;i<10;i++){
               System.out.println("Thread");
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   throw new RuntimeException(e);
               }
           }
        });
        t.start();
        Thread.sleep(3000);
        System.out.println("Main");
    }
}

上述代码中,t线程中我们循环打印Thread,每打印一次休眠1秒钟,在main线程中,我们先start线程,接着使main线休眠3秒.接着打印Main.这里我们就发现,线程调度本身是抢占实执行的,但是此刻main线程会等待t线程3秒钟,接着再继续执行. 

        

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值