目录

1.创建线程

1.2:run()和start()方法

1.3:Thread的几个常见属性

2.线程的有关操作

2.1:启动一个线程:start()

2.2:中断一个线程

2.2.1:使用自定义的变量来作为标志位

2.2.2:使用Thread.interrupted()代替自定义标志位

2.2.3:标志位不会被清除 Thread.currentThread().isInterrupted()

2.3:等待一个线程  join()

2.4:获取当前线程引用  currentThread()

2.5:休眠当前线程 slepp()


前言:

在前一篇我们了解了何为线程和进程,并大致的知道线程和进程之间的区别和联系,今天我们进一步的来了解线程,该怎么创建一个线程。

1.创建线程

class MyThread extends Thread{
    @Override
    public void run() {
        System.out.println("这里是继承Thread来创建一个线程类");
    }
}
//实现Runnable接口来创建线程
class  MyRunnable implements   Runnable{
    @Override
    public void run() {
        System.out.println("实现Runnable接口来创建一个线程类");
    }
}
public class ThreadDemo1 {
    public static void main(String[] args) {
        //继承Thread来创建一个线程类
        MyThread thread=new MyThread();
        thread.start();
        //这里就是描述一个任务
        MyRunnable runnable=new MyRunnable();
        //把任务交给一个线程来完成。
        Thread thread1=new Thread(runnable);
        thread1.start();
        //利用lambda来创建一个线程
        Thread thread2=new Thread(()->{
            System.out.println("这是lambda来创建一个线程。");
        });
        thread2.start();
    }
}

 看代码,里面有很多run(),start()方法,为啥有这些呢?接下来我们来进一步了解run()方法,start()方法


1.2:run()和start()方法

1. start()是真正的操作系统中创建一个新的线程。是真正的实现了多线程。

2. start()方法启动线程后自动调用run()方法。

3. run()方法只是描述了线程要干的活是啥,如果在main中调用run()方法,此时run()只是Thread类的一个普通的方法。并不会创建一个新的线程。

4. run()方法执行完毕后,start()创建的这个新线程会立马销毁,Thread对象但依旧存在(对象的生命周期和系统内核的线程并非完全一致)。

1.3:Thread的几个常见属性

1.ID  getId():

ID是线程的唯一标识,不同线程不会重复。

2.名称 getName():

3.是否后台线程:isDaemon():

后台线程又叫做守护线程,main默认是前台线程,JVM自带的线程都是后台线程。JVM会在一个进程的所有非后台线程结束后,才会结束运行。前台线程会阻止进程结束,前台线程的工作没做完,进程是结束不了的。

4.是否存活:isAlive():

这个是判断内核里面的PCB是否在干活,是在判断当前系统里面的这个线程是不是真的存在。也可以简单的理解,run()方法是否允许结束了。

2.线程的有关操作

2.1:启动一个线程:start()

前面已经讲述了,这里就不在讲述呢

2.2:中断一个线程

这里的中断,并不是让一个线程立即停止下来,而是通知线程,你该停下来了,但至于这个线程会不会停下来,是取决线程自己的(线程内部的代码)。

2.2.1:使用自定义的变量来作为标志位

public class ThreadDemo2 {
    private  static  boolean flag=false;
    public static void main(String[] args) throws InterruptedException {
     Thread t1=new Thread(()->{
            while(!flag){
                System.out.println("没被发现,可以继续潜伏");
            }
         System.out.println("快撤!!");
     });
     t1.start();
     Thread.sleep(1);
     flag=true;
    }
}

2.2.2:使用Thread.interrupted()代替自定义标志位

为true:就是被终止了

public static void main(String[] args) throws InterruptedException {
        Thread t1=new Thread(()->{
            while(!Thread.currentThread().isInterrupted()){
                System.out.println("她不在,可以继续布置");
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.println("她来了,快撤");
        });
        t1.start();
        Thread.sleep(1);
        t1.interrupt();//这个就是将t1这个线程中断
    }
}

这里Thread.currentThread():是可以获取当前的线程。

使用Thread.isInterrupted():是会把sleep()方法提前唤醒。

 public static void main(String[] args) throws InterruptedException {
        System.out.println("原本的中断标志位为:"+Thread.interrupted());
        //这里打印出来Thread.interrupted()是false;
        Thread t1=new Thread(()->{
            for (int i = 0; i <3; i++) {
                System.out.println("现在的中断标志位为"+Thread.interrupted());
            }
        });
        t1.start();
        t1.interrupt();//这里是将中断标志位设置为true;
    }

Thread.isInterrupted()  判断当前线程的中断标志被设置后,会清除自己设置的中断标志,使中断标志恢复原来。就像弹簧一样,按下去,就自己恢复到原来的长度。


2.2.3:标志位不会被清除 Thread.currentThread().isInterrupted()

public static void main(String[] args) throws InterruptedException {
        System.out.println("原本的中断标志位为:"+Thread.interrupted());
        //这里打印出来Thread.interrupted()是false;
        Thread t1=new Thread(()->{
            for (int i = 0; i <3; i++) {
                System.out.println("现在的中断标志位为"+Thread.currentThread().isInterrupted());
            }
        });
        t1.start();
        t1.interrupt();//这里是将中断标志位设置为true;
    }

Thread.currentThread().isInterrupted(): 判断指定线程的中断标志被设置,不会清除设置的中断标志位。就像闹钟响了,你把闹钟暂停了,但过一会儿还是回响。


2.3:等待一个线程  join()

线程是一个随机调度的过程,而等待一个线程就是控制线程的结束顺序。


join()  等待t1线程结束,t1线程不结束,main线程就进入阻塞状态.如果在执行join()之前,t 已经结束了,main这个线程就不会阻塞,直接往下走。

 

这里为啥不一样呢?

join(参数)这里是毫秒,意思就是我最多等待多久,你来晚了,我就走了。这里只看你设置的参数是多久。但是在我设置等待的时间内t1线程已经结束了,main线程也不会继续处于阻塞状态,也会立马运行下去。 


2.4:获取当前线程引用  currentThread()

  public static void main(String[] args) {
        Thread thread=Thread.currentThread();//获取当前线程
        System.out.println(thread.getName());
    }

在哪个线程中调用,就可以获取到当前线程的实例。getName()获取到线程的名字。

如上代码,的结果就是main。

2.5:休眠当前线程 slepp()

休眠当前线程就用Sleep(),它的举例已经在上面使用过了。这里就不在举例了。

总结:

以上就是我总结的线程的知识点,若有错的,或是不太准确的,请各位铁子留言指错,若感觉不错,请一键三连。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐