Thread 类的基本用法

线程创建

(1)继承thread类,重写run方法

class MyThread extends Thread{
    @Override
    public void run() {
        while (true) {
            System.out.println("hello thread");
        }
    }
}//创建一个线程,打印"hello thread"

(2)实现Runnable接口,重写run方法

class runnable implements Runnable{


    @Override
    public void run() {
        while (true){
            System.out.println("hello thread");
        }
    }
}

(3)继承thread,重写run,使用匿名内部类

public class Test {
    public static void main(String[] args) {
        Thread t=new Thread(){
            @Override
            public void run() {
                while (true){
                    System.out.println("hello thread");
                }
            }
        };
        t.start();
        while (true){
            System.out.println("hello main");//主线程打印"hello main"
            
        }
    }
}

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

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

(5)使用lambda表达式(最常用)

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

线程中断

在java中,想要销毁或终止一个线程,就是让run方法尽快执行完毕。

1 通过手动添加一个标志位来作为run执行结束的条件。

public class test {
    private static boolean isQuit=false;//定义一个成员变量
    public static void main(String[] args) {
        Thread t=new Thread(()->{
while (!isQuit){
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
    System.out.println("线程工作中");
}
            System.out.println("线程工作完毕");
        });
        t.start();
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
isQuit=true;
        System.out.println("设置isQuit为true");
    }
}

需要注意isQuit是作为类的成员变量,不能写在main里面(变成了局部变量),涉及到lambda的变量捕获规则。

结果

上述代码手动设置了一个成员变量isQuit为标志位,一开始isQuit为false,while里面的循环条件成立,所以子线程会持续打印” 线程工作中“,当主线程休眠时间结束,并且把isQuit设置为true,子线程循环条件不成立,线程结束工作。

上述方法需手动创建标志位,稍微麻烦了一点,并且可以看到当子线程在sleep时主线程修改isQuit,线程并不能及时响应(可以看到运行结果:在修改变量之后,子线程还是执行了一次打印)

有另一种方法可以完成线程的中断。通过thread内部的标志位

public class test {
    public static void main(String[] args) {
     Thread t=new Thread(()->{
         while (!Thread.currentThread().isInterrupted()) {//Thread.currentThread是当前实例, 
                                                           // 相当于实例化一个t.
             try {
                 Thread.sleep(1000);
             } catch (InterruptedException e) {
                e.printStackTrace();
             }
             System.out.println("线程工作中");
         }
     });
       t.start();
       try {
           Thread.sleep(5000);
       }catch(InterruptedException e) {
           e.printStackTrace();
        }

        System.out.println("让线程终止");
        t.interrupt();
    }
}

运行结果

可以看到,中断后线程确实抛出异常了,但是并没有停止。这样的机制是java期望当线程收到中断信号时,能自由决定怎么处理,让我们有更多的可操作空间,前提这个可操作空间是通过抛出异常唤醒的(如果没有sleep,就没有这个操作空间了)。

接下来线程可以

1继续执行,假装什么也没听见。

2加上一个break,让线程结束。

3放一些其他工作代码,等完成后在结束。

public class test {
    public static void main(String[] args) {
     Thread t=new Thread(()->{
         while (!Thread.currentThread().isInterrupted()) {//Thread.currentThread是当前实例, 
                                                           // 相当于实例化一个t.
             try {
                 Thread.sleep(1000);
             } catch (InterruptedException e) {
              //1假装什么也没听见,继续执行
                e.printStackTrace();
             break;//2设置break让线程结束
               //3做一些其他工作,等完成后再结束

             }
             System.out.println("线程工作中");
         }
     });
       t.start();
       try {
           Thread.sleep(5000);
       }catch(InterruptedException e) {
           e.printStackTrace();
        }

        System.out.println("让线程终止");
        t.interrupt();
    }
}

运行结果

可以看到在添加break后,线程确实结束了。

线程等待

一个线程等待另一个线程结束,本质上就是控制线程执行顺序。通过join方法完成。

public class test {
    public static void main(String[] args) throws InterruptedException{
        Thread t=new Thread(()->{
            for (int i = 0; i < 5; i++) {
                System.out.println(i);
            }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
        });
        t.start();
        System.out.println("等待开始");
       // 让主线程来等待 t 线程执行结束.
        // 一旦调用 join, 主线程就会触发阻塞. 此时 t 线程就可以趁机完成后续的工作.
        // 一直阻塞到 t 执行完毕了, join 才会解除阻塞, 才能继续执行
        t.join();
        System.out.println("等待结束");
    }
}

运行结果

当然也可以调用带有时间参数的join方法设置等待最长时间。

线程休眠

调用sleep()方法,要注意的是sleep是存在精度误差的,不是说时间一到立马执行,因为系统的调度也要花费一定的时间。

public class test {
    public static void main(String[] args) throws InterruptedException {
        long beg=System.currentTimeMillis();
        Thread.sleep(1000);
        long end=System.currentTimeMillis();
        System.out.println(end-beg);
    }
}

执行结果

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值