阅读 127

线程及其常见方法总结

线程及其常见方法总结

线程与进程的区别:


进程是系统分配资源的最小单位,线程时系统调度的最小单位 ,一个进程内的线程之间是可以共享资源的。


资源开销:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。

包含关系:如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。

内存分配:同一进程的线程共享本进程的地址空间和资源,而进程之间的地址空间和资源是相互独立的

影响关系:一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮。

执行过程:每个独立的进程有程序运行的入口、顺序执行序列和程序出口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制,两者均可并发执行

每个进程至少有一个线程存在,即主线程(系统级别的,C语言的主线程) Java级别的主线程:自己写的入口函数main方法(可以没有这个线程)

静态内部类:


package lesson1;


public class InnerClass {

    //静态内部类,和普通类使用没有什么区别,只是需要明确是哪个类的内部类

    //在其他包中使用时:InnerClass.A()

    public static class A{}

}

1

2

3

4

5

6

7

package ll;


import lesson1.InnerClass;


public class B {

    public static void main(String[] args) {

        //静态内部类的调用

        new InnerClass.A();

    }

}

1

2

3

4

5

6

7

8

9

10

******************************************************************************************************************

创建线程的方法:


package lesson1;


public class ThreadLook1 {

    static class MyThread extends Thread {

        @Override

        public void run() {

            System.out.println("创建线程方法一:继承Thread类");

        }

    }

    static class MyThread1 implements Runnable{

        @Override

        public void run() {

            System.out.println("创建线程方法二:实现Runnable接口");

        }

    }


    public static void main(String[] args) {

        MyThread t = new MyThread();

        t.start();

        

        Thread t1 = new Thread(new MyThread1());

        t1.start();

    }



    public static void main1(String[] args) {


        //创建线程 方法三

        Thread t1 = new Thread() {

            @Override

            public void run() {

                System.out.println("使用匿名类创建Thread子类对象");

            }

        };

        t1.start();


        //创建线程 方法四

        Thread t2 = new Thread(new Runnable() {

            @Override

            public void run() {

                System.out.println("使用匿名类创建Runnable子类对象");

            }

        });

        t2.start();


        //创建线程 方法五 使用lambda表达式创建Runnable子类对象

        Thread t3 = new Thread(() -> System.out.println("使用匿名类创建Thread子类对象"));

        Thread t4 = new Thread(() ->{

            System.out.println("使用匿名类创建Thread子类对象");

        });

    }

}


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

******************************************************************************************************************

Thread常见的使用方法


方法 说明

Thread() 创建线程对象

Thread(Runnable target) 使用Runnable对象创建线程对象

Thread(String name) 创建线程对象,并命名

Thread(Runnable target,String name) 使用Runnable对象创建线程对象,并命名

示例:


Thread t1 = new Thread();

Thread t2 = new Thread(new MyThread1());

Thread t3 = new Thread("线程名称");

Thread t4 = new Thread(new MyThread1(),"线程名称");

1

2

3

4

******************************************************************************************************************

Thread常见的属性


属性 获取方法

ID getId()–线程的唯一标识,不会重复

名称 getNmae()

状态 getState()

优先级 getPriority() --优先级高的线程理论上更容易被调度到

是否后台(守护)线程 getDaemon()–JVM会在一个进程的所有非后台线程结束后才会结束运行

是否存活 isAlive()–run方法是否结束

是否被中断 isInterrupted()

示例:


package lesson1;


public class ThreadLook4 {

    public static void main(String[] args) {

        Thread t = new Thread(new Runnable() { //子线程

            @Override

            public void run() {

                while (true) {


                }

            }

        },"main子线程"); //命名

        t.start();

        System.out.println(t.getId());  //12

        System.out.println(t.getName());  //main子线程

        System.out.println(t.getState()); //RUNNABLE

        System.out.println(t.getPriority()); //5

        System.out.println(t.isDaemon()); //false

        System.out.println(t.isAlive());  //true

        System.out.println(t.isInterrupted()); //fals

    }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

运行结果如下:注意此时线程还未结束运行(关于守护线程的测试)


当在t.start()线程启动之前使用t.setDaemon(true)设置守护线程之后再运行程序,程序结束运行。也就是说,对于Java线程,只要有一个非守护线程还没有终止,进程就不会结束。



同时对于Thread.currentThread().getName 和 t.getName() this.getName()三者之间的不同需要注意

总结:


Thread提供静态方法currentThread()来供我们调用,可以避免this无法获取到main线程的问题。


通过继承Thread 创建线程时,可以使用this关键字去调用继承自父类Thread的方法,this就是当前的对象。


Thread.currentThread()可以获取当前线程的引用,一般都是在没有线程对象又需要获得线程信息时通过Thread.currentThread()获取当前代码段所在线程的引用,且通过Runnable接口实现线程创建时,在run()里面只能使用Thread.currentThread()


public static void main(String[] args) {


        Thread t = new Thread() {

            @Override

            public void run() {

                System.out.println(this.getName() + "  Thread + this + run"); //Thread-0  Thread + this + run

                //System.out.println(t.getName()); //编译错误

                System.out.println(Thread.currentThread().getName() + "  Thread + current + run"); //Thread-0  Thread + current + run

            }

        };

        t.start();

        //System.out.println(this.getName); //编译错误

        System.out.println(t.getName() + "  Thread + t.getName"); //Thread-0  Thread + t.getName

        System.out.println(Thread.currentThread().getName() + "  Thread + current"); //main  Thread + current



        Thread t1 = new Thread(new Runnable() {

            @Override

            public void run() {

                //System.out.println(this.getName); //编译错误

                //System.out.println(t1.getName()); //编译错误

                System.out.println(Thread.currentThread().getName() + "  Runnable + current + run"); //Thread-1  Runnable + current + run

            }

        });

        t1.start();

        //System.out.println(this.getName); //编译错误

        System.out.println(t1.getName() + "  Runnable + t.getName");   //Thread-1  Runnable + t.getName

        System.out.println(Thread.currentThread().getName() + "  Runnable + current"); //main  Runnable + current

        


        Thread.currentThread().setName("主线程");

        System.out.println(Thread.currentThread().getName()); //主线程

    }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

start() VS run() —区别


基础认识:代码在哪个线程执行,就是由哪个线程执行代码行


start() 会向系统申请启动某个线程,如果该线程处于运行状态,会自动执行run()


run() 通过 Thread 或者 Runnable 类定义要执行的任务代码,即线程再运行态执行的代码 如果不调用start() 而直接调用 run()[线程体] ,相当于Java对象直接调用普通实例方法.


start 启动线程 ,线程处于就绪态,并没有运行,一旦得到cpu时间片,就开始执行run()方法,这时此线程处于运行态,这里方法 run()称为线程体,它包含了要执行的这个线程的内容,run方法运行结束,此线程随即终止。

******************************************************************************************************************

PS:

如何同时启动多个线程?

代码如下:


package lesson1;


public class ThreadLook2 {

    public static void main(String[] args) {

        //同时启动20个线程 每个线程从 0+1的方式加到99;

        for (int i = 0; i < 20;i++) {

            Thread t = new Thread(new Runnable() {

                @Override

                public void run() { //在多线程环境下,即使同一段代码块,也是可以并发并行执行

                    for (int i = 0; i < 100;i++) {

                        if (i == 99 ) {

                            System.out.println(i);

                        }

                    }

                }

            });

            t.start();

        }


    }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

注意:某个线程抛run异常 整个线程结束 但是不会影响其他线程


package lesson1;


public class ThreadLook3 {

    public static void main(String[] args) {

         Thread t = new Thread(new Runnable() { //子线程

             @Override

             public void run() {

                 for(int i = 0; i < 10;i++) {

                     if(i == 6) {

                         //某个线程抛run异常 整个线程结束 但是不会影响其他线程

                         //线程中处理异常的方式 线程对象.setUncaughtExceptionHandler()

                         //或者自己在run()方法里捕获

                         throw new RuntimeException();

                     }

                     System.out.println(i);

                 }

             }

         },"main子线程"); //命名

         t.start();

         while (true) { //main线程


         }

         //子线程结束 main线程继续

    }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

运行结果如下:此时虽然run线程结束,但是main线程还没有结束


————————————————

版权声明:本文为CSDN博主「柠七99」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/m0_46657493/article/details/114686894


文章分类
后端
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐