Thread类

多线程系列文章目录


在这里插入图片描述

如果你觉得我的文章有帮助到你,还请【关注➕点赞➕收藏】,得到你们支持就是我最大的动力!!!

版权声明:本文由【马上回来了】原创、在CSDN首发、需要转载请联系博主。
版权声明:本文为CSDN博主「马上回来了」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

在这里插入图片描述

新的知识开始喽
在这里插入图片描述

文章目录

  • 多线程系列文章目录
  • 1.线程的创建
    • 1.1创建一个线程
    • 1.2Thread(Runnable target, String name)
  • 2.Thread常见属性
  • 3.启动一个线程start方法
  • 4.获取当前线程的引用
  • 5.中断一个线程interrupt
  • 6.等待一个线程join方法
  • 7.休眠当前线程
  • 8.操作系统的状态


1.线程的创建

线程是操作系统里的概念,操作系统内核实现了这样的机制,并且对用户提供了API供用户使用.
java标准库中Thread可以视为是对操作系统提供的API进行了进一步的抽象和封装.

1.1创建一个线程

①自定义子类继承Thread类

class MyThread extends Thread{
    @Override
    public void run() {
        while (true){
            System.out.println("hello thread");
            try {
                Thread.sleep(1_000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }


    }
}
public class Demo1 {
    public static void main(String[] args) {
        MyThread t = new MyThread();
        t.start();
        while (true){
            System.out.println("hello main");
            try {
                Thread.sleep(1_000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

②自定义类实现Runnable接口

class MyRunnable implements Runnable{
    @Override
    public void run() {
        while (true){
            System.out.println("hello thread");
            try {
                Thread.sleep(1_000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class Demo2 {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread1 = new Thread(myRunnable);
        thread1.start();
        Thread thread2 = new Thread(myRunnable);
        thread2.start();
        while (true){
            System.out.println("hello main");
            try {
                Thread.sleep(1_000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

③创建Thread的匿名内部类

public class Demo3 {
    public static void main(String[] args) {
        //Thread匿名内部类
        Thread thread = new Thread(){
            @Override
            public void run() {
                System.out.println("hello thread");
                try {
                    Thread.sleep(1_000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        thread.start();

        while (true){
            System.out.println("hello main");
            try {
                Thread.sleep(1_000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

④创建Runnable的匿名内部类

public class Demo4 {
    public static void main(String[] args) {
        //runnable匿名内部类作为参数传给Thread的构造方法
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello thread");
                try {
                    Thread.sleep(1_000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread.start();
        while (true){
            System.out.println("hello main");
            try {
                Thread.sleep(1_000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

⑤lambda表达式

public class Demo5 {
    public static void main(String[] args) {
        //lambda表达式
        Thread thread =new Thread(()->{}){
            @Override
            public void run() {
                System.out.println("hello thread");
                try {
                    Thread.sleep(1_000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        thread.start();
        while (true){
            System.out.println("hello main");
            try {
                Thread.sleep(1_000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

1.2Thread(Runnable target, String name)

String name是给线程取名字,如果没有给线程取名字,操作系统会自动生成名字.
构造方法里传了String name

public class Demo7 {
    public static void main(String[] args) {
       Thread thread = new Thread(()->{
           while (true){
               System.out.println("hello thread");
               try {
                   Thread.sleep(1_000);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }

       },"这是我的多线程");
       thread.start();
        System.out.println("main线程执行结束");
    }
}

Thread类_第1张图片
构造方法里没有传String name

public class Demo7 {
    public static void main(String[] args) {
       Thread thread = new Thread(()->{
           while (true){
               System.out.println("hello thread");
               try {
                   Thread.sleep(1_000);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }

       });
       //将thread进程设置为后台进程
        //必须在start启动前设置,调用start之后就无法在设置为后台进程
       //thread.setDaemon(true);//main进程结束后,thread是后台进程,所以thread进程会自动结束
       thread.start();
        System.out.println("main线程执行结束");//这里线程默认是前台进程,即使是main线程结束,thread进程默认是前台进程,前台进程会阻止进程退出,所以thread进程不会就结束
    }
}

Thread类_第2张图片

2.Thread常见属性

线程ID
Thread类_第3张图片
线程名
Thread类_第4张图片
线程状态
Thread类_第5张图片
线程优先级
Thread类_第6张图片
是否被中断

Thread类_第7张图片
是否是存活
Thread类_第8张图片
是否是后台进程:默认创建的进程是前台进程,前台进程如果执行完了会阻止进程退出,而后台进程执行完了,不会阻止阻止进程退出,main就是前台进程.
如果所有的前台进程都执行完了,及时后台进程没有执行完,进程也会退出.
Thread类_第9张图片

public class Demo {
    public static void main(String[] args) {
        Thread thread = new Thread(()->{
            while(true){
                System.out.println("hello thread");
                try {
                    Thread.sleep(1_000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"这是俺的线程");
        thread.start();

        System.out.println(thread.getId());//12
        System.out.println(thread.getName());//这是俺的线程
        System.out.println(thread.getPriority());//5
        System.out.println(thread.isDaemon());//false
        System.out.println(thread.getState());//TIMED_WAITING
        System.out.println(thread.isAlive());//true
        System.out.println(thread.isInterrupted());//false
    }
}

运行结果:
Thread类_第10张图片

3.启动一个线程start方法

Thread类_第11张图片
当Thread创建好了一个线程对象时,并且重写了run方法时,线程并没有开始执行,也就是操作系统底层还没有创建出一个正真的线程,只有当调用start方法后,操作系统底层才会正真的创建出一个线程(PCB)并且执行这个线程.
这里要注意run方法与start方法的区别:
run方法只是去安排线程要执行的任务,并没有创建线程;
start方法则是在操作系统内核里创建出了一个线程(PCB)

4.获取当前线程的引用

注意currentThread是静态方法
Thread类_第12张图片

5.中断一个线程interrupt

这篇文章线程中断里详细的讲解了线程中断的几种方式。

6.等待一个线程join方法

线程之间的调度顺序是不确定的,可以通过一些特殊操作来对调度的顺序进行干预,其中join方法就可以控制线程之间执行的顺序。

看下面代码:

public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(){
            @Override
            public void run() {
                System.out.println("t线程开始" );
                for (int i = 0; i < 10; i++) {
                    System.out.println(i);
                }
                System.out.println("t线程结束");

            }

        };
        t.start();
        t.join();
        System.out.println("main线程开始");
        System.out.println("main线程结束");
    }

Thread类_第13张图片

运行结果:
Thread类_第14张图片
注意如果t线程在join之前就已经结束了,那么main线程就不会在阻塞等待了。
join还有时间参数的重载方法:
Thread类_第15张图片

7.休眠当前线程

Thread里提供了sleep方法,这个方法可以使线程休眠一会儿,也就是使线程阻塞一会儿

 public static void main(String[] args) {
        Thread t = new Thread(){
            @Override
            public void run() {
                System.out.println("t线程开始休眠1s");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("t线程休眠结束");
            }
        };
        t.start();
    }

Thread类_第16张图片
运行结果:
Thread类_第17张图片
Thread类_第18张图片
那么问题来了,如果sleep参数是1s,那么线程真的是只休眠一秒吗?
不一定!!!
一般会多余1s,多多少具体看操作系统调度的时间开销,可能快(<1ms)也可能慢(>10s),而对于一般的操作系统的调度时间开销是不可预期的,有时候快,有时候慢。

8.操作系统的状态

在操作系统里已经对pcb已经有了一个状态的描述,java里觉得这个描述不太合适,所以又自己弄了一套状态规则:
Thread类_第19张图片



今天的你看懂这里又学到了很多东西吧

在这里插入图片描述

下次见喽
在这里插入图片描述

你可能感兴趣的:(java多线程,java)