目录
线程创建有五种方法,这里喜欢用那种用那种
注意:下文中的start方法才是多线程开始执行,run方法只是表明需要执行的内容
-
- 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方法,相当于是在给线程分配任务
- 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();
- }
- }
-
- public class Main {
- public static void main(String[] args) {
-
-
- Thread c = new Thread(){
- @Override
- public void run() {
- System.out.println("通过匿名内部类继承Thread来创建");
- }
- };
- c.start();
- }
- }
- 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();
-
-
- }
- }
- public class Main {
- public static void main(String[] args) {
-
-
- Thread e = new Thread(()-> System.out.println("使用lambda表达式创建"));
- e.start();
-
-
-
- }
- }
最后我们看一下所有的执行结果
总结:
可以发现,只有通过继承Thread类的时候,不需要创建Thread对象,其余的都需要创建Thread对象
这种方法很简单,就是自己定义一个变量,用来标识线程结束,当执行某条语句,则线程结束,就不进行演示了
不仅可以用自定义的标志位,我们还可以调用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方法是线程实例中的方法,不是类方法,所以我们需要通过引用来调用
在多线程中,一个线程等待另一个线程,通常使用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执行结束了,才开始执行主线程后面的内容,这就是线程的等待
线程休眠我们通常使用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来处理,这个我们在异常的时候已经说过了,就不再赘述了
这里我们使用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的实例调用,其实结果都是一样的,只有一个,就是当前线程的引用
以上就是多线程的一些基本使用了
感谢阅读