一篇文章带你理解Thread(多线程)的基础用法

目录

1.线程创建

1.1通过继承类创建

1.2通过类实现接口创建

1.3通过内部类继承Thread来创建

1.4通过内部类实现Runnable接口来创建

1.5通过lambda表达式创建

2.线程中断

2.1自定义标志位

2.2interrupt()方法

3.线程等待

4.线程休眠

5.获取线程实例


1.线程创建

        线程创建有五种方法,这里喜欢用那种用那种

注意:下文中的start方法才是多线程开始执行,run方法只是表明需要执行的内容

1.1通过继承类创建


class A extends Thread {
    @Override
    public void run() {
        System.out.println("通过继承Thread类创建线程");
    }
}



public class Main {
    public static void main(String[] args) {
        A a = new A();
        //这里的start是线程开始执行的方法,执行的是Thread中的run方法
        a.start();
    }
}

这里需要注意,当我们继承Thread类的时候,必须重新run方法,相当于是在给线程分配任务

1.2通过类实现接口创建

class B implements Runnable{
    @Override
    public void run() {
        System.out.println("通过实现Runnable接口来创建");
    }
}


public class Main {
    public static void main(String[] args) {

        //这里通过Thread类型对象,对构造方法传入一个实现了Runnable接口的类来创建
        Thread b = new Thread(new B());
        b.start();
    }
}

1.3通过内部类继承Thread来创建


public class Main {
    public static void main(String[] args) {
     

        Thread c = new Thread(){
            @Override
            public void run() {
                System.out.println("通过匿名内部类继承Thread来创建");
            }
        };
        c.start();
    }
}

1.4通过内部类实现Runnable接口来创建

public class Main {
    public static void main(String[] args) {
    
        Thread d = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("通过匿名内部类实现Runnable接口来实现");
            }
        });
        d.start();

        
    }
}

1.5通过lambda表达式创建

public class Main {
    public static void main(String[] args) {
 

        Thread e = new Thread(()-> System.out.println("使用lambda表达式创建"));
        e.start();



    }
}

最后我们看一下所有的执行结果

总结:

可以发现,只有通过继承Thread类的时候,不需要创建Thread对象,其余的都需要创建Thread对象

2.线程中断

2.1自定义标志位

这种方法很简单,就是自己定义一个变量,用来标识线程结束,当执行某条语句,则线程结束,就不进行演示了

2.2interrupt()方法

不仅可以用自定义的标志位,我们还可以调用interrupt方法,来进行线程中断


public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            //通过Thread.interrupted()判断是否存在标志位,若不存在则一直执行while,若存在则停止并且清除标志位
           while(!Thread.interrupted()){
               System.out.println("123");
           }
        });
        t1.start();
        Thread.sleep(1);
//通过t1.interrupt()创建标志位
        t1.interrupt();
    }
}

上述代码中的含义是,开始没标志位,所以while语句可以一直执行,当我们执行到t1.interrupt之后,创建了一个标志位,这样我们就拥有了标志位,所以while循环就会终止,代码的运行结果如下

可以看到我们的线程是有停止的

 我们总结一些常用的标志位用法

1.Thread.interrupt()       设置标志位,若线程阻塞则抛出异常,并且清除标志位

2.Thread.interrupted()     判断是否有标志位,若存在返回true,否则返回false,最后清除标志位 

3.Thread..currentThread().isInterrputed()      判断是否有标志位,若存在返回true,否则返回false,最后不清除标志位 

第三个个currentThread是得到当前线程的引用,通过这个引用再去调用isInterrputed方法

 

可以看到,isInterrupted方法是线程实例中的方法,不是类方法,所以我们需要通过引用来调用

3.线程等待

在多线程中,一个线程等待另一个线程,通常使用jion()方法

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                System.out.println("别急,我还没结束呢");
            }
            System.out.println("我结束了");
        });
        t1.start();
        t1.join();
        System.out.println("你终于结束了");
    }
}

看这段代码,就是让主线程去等待t1线程,就是通过调用t1的join()方法来实现的,看一下运行结果

可以看到,当我们的主线程走到t1.join()之后,进行了阻塞等待,然后等t1执行结束了,才开始执行主线程后面的内容,这就是线程的等待

4.线程休眠

线程休眠我们通常使用sleep方法,这个方法是存在于Thread中的类方法,需要传入一个参数,单位是毫秒,就是让当前线程阻塞等待多长时间之后,再执行,看具体实现

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                System.out.println("别急,我还没结束呢");
            }
            System.out.println("我结束了");
        });
        t1.start();

        Thread.sleep(1);
        System.out.println("============================================================");
    }
}

看这样一段代码,我们让主线程一秒后打印一串'=',当我们运行线程的时候

可以看到,主线程等待一秒后,打印了=,但是t1并未执行结束,但是我们的主线程调用的是sleep方法,所以并不会无限制的等下去

注意:这里的sleep需要处理编译异常,

InterruptedException

 

我们可以像上面一样加上声明,也可以使用try{}catch来处理,这个我们在异常的时候已经说过了,就不再赘述了

 

5.获取线程实例

这里我们使用currentThread来获取线程的实例,这里和this有异曲同工之妙,在哪里调用的,就会获取到哪个实例,看代码实现

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            System.out.println(Thread.currentThread());
        });
        t1.start();
        System.out.println(Thread.currentThread());
       
    }
}

运行结果是这样的

我们可以看到,在main中的是main线程,t1是Thread-0线程,我们做个测试,如果,在主线程中通过t1来调用currentThread获取到的是哪个线程呢?

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            
        });
        t1.start();
        
       
        System.out.println(t1.currentThread());
    }
}

 我们可以看到,我们在主线程中通过t1去调用currentThread()方法,得到结果也是和我们预期的一样

为什么?

因为我们的currentThread()是一个静态方法,所以不论你通过什么Thread的实例调用,其实结果都是一样的,只有一个,就是当前线程的引用 

以上就是多线程的一些基本使用了

        感谢阅读

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值