线程及其常见方法总结

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


线程与进程的区别
(1)进程是系统分配资源的最小单位,线程是系统调度的最小单位
(2)进程有自己的内存地址空间,线程只独享指令流执行的必要资源,如寄存器和栈
(3)由于同一进程的各线程之间共享内存和文件资源,可以不通过内核进行直接通信
(4)线程的创建、切换及终止效率更高(线程的创建、切换、终止也比较耗时,这里只是相对于进程来说效率更高)

静态内部类:

package lesson1;

public class InnerClass {
    //静态内部类,和普通类使用没有什么区别,只是需要明确是哪个类的内部类
    //在其他包中使用时:InnerClass.A()
    public static class A{}
}
package ll;

import lesson1.InnerClass;

public class B {
    public static void main(String[] args) {
        //静态内部类的调用
        new InnerClass.A();
    }
}

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

创建线程的方法:

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子类对象");
        });
    }
}


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

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(),"线程名称");

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

Thread常见的属性

属性获取方法
IDgetId()–线程的唯一标识,不会重复
名称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
    }
}

运行结果如下:注意此时线程还未结束运行(关于守护线程的测试)
在这里插入图片描述
当在t.start()线程启动之前使用t.setDaemon(true)设置守护线程之后再运行程序,程序结束运行。也就是说,对于Java线程,只要有一个非守护线程还没有终止,进程就不会结束。
在这里插入图片描述


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

总结:

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

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

  3. 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()); //主线程
    }

start() VS run() —区别

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

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

  3. 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();
        }

    }
}

注意:某个线程抛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线程继续
    }

运行结果如下:此时虽然run线程结束,但是main线程还没有结束
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值