线程的创建方法及Thread类的常见方法

线程是为了解决并发编程引入的机制, 线程相比于进程来说,更轻量
进程是操作系统资源分配的基本单位 , 线程是操作系统调度执行的基本单位

1、创建线程的五种方法

1.1 继承 Thread类 ,重写 run方法

class MyThread extends Thread{
    @Override
    public void run() {
        while (true){
            System.out.println("hello thread");
            //为了让这里的打印放慢点,方便观察,  加个sleep
            try {
                Thread.sleep(1000);    //1秒
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

public static void main(String[] args) {
	Thread thread=new MyThread();      //父类引用指向子类实例 子类的方法会被动态绑定的机制,被调用到
    thread.start();   //线程中的特殊方法,  创建了一个新的线程 (启动一个线程),  新的线程负责执行thread.run()
}

1.2 实现 Runnable 接口, 重写 run方法

Runnable接口的作用,是描述一个 "要执行的任务" , run方法就是任务的执行细节

class MyRunnable implements Runnable{
    @Override
    public void run() {
        System.out.println("hello world");
    }
}
    public static void main(String[] args) {
        //这只是描述了个任务
        Runnable runnable=new MyRunnable();
        //把任务交给线程来执行
        Thread thread=new Thread(runnable);
        thread.start();
    }

1.3 使用匿名内部类,创建 Thread子类对象

    public static void main(String[] args) {
        Thread thread=new Thread(){   //匿名内部类: 创建了一个Thread的子类,(该子类没有名字,所以叫“匿名”)
            @Override
            public void run() {
                System.out.println("hello");;
            }
        };
        thread.start();
    }

1.4 使用匿名内部类, 创建 Runnable子类对象

    public static void main(String[] args) {
        Thread thread=new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello");
            }
        });
        thread.start();
    }

1.5 使用 lambda 表达式 ,创建 Runnable子类对象

lambda 表达式: ()->{函数体}

Lambda就是个匿名函数(没有名字的函数),用一次就销毁,

    public static void main(String[] args) {
        Thread thread=new Thread(()->{
            System.out.println("hello thread");
        });
        thread.start();
    }

2. Thread类 及 常见方法

Thread 类是 JVM 用来管理线程的一个类,换句话说,每个线程都有一个唯一的 Thread 对象与之关联。
Thread 类的对象就是用来描述一个线程执行流的,JVM 会将这些 Thread 对象组织起来,用于线程调度,线程管理。

2.1 Thread 的常见构造方法

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

2.2 Thread 的几个常见属性

属性获取方法
IDgetId()
名称getName()
状态getState()
优先级getPriority()
是否后台线程isDaemon()
是否存活isAlive()
是否被中断isInterrupted()

2.3 启动一个线程-start()

前面已经介绍了如何通过复写 run方法创建一个线程对象,但线程对象被创建出来并不意味着线程就开始运行了。

  • 覆写 run 方法是提供给线程要做的事情的指令清单
  • 线程对象可以认为是把 李四、王五叫过来了
  • 而调用 start() 方法,就是喊一声:”行动起来!“,线程才真正独立去执行了。

调用 start()方法,才真的在操作系统的底层创建出一个线程。

2.4 中断一个线程

一个线程一旦进入到工作状态,他就会按照任务的步骤去进行工作,不完成时不会结束的,但有时我们需要增加一些机制,涉及到了停止线程的方式。

常见的有以下两种方式:

  1. 通过共享的标记来进行沟通
  2. 调用 interrupt()方法来通知

示例-1: 使用自定义的变量来作为标志位(需要给标志位上加 volatile 关键字)

public class ThreadDemo {
    private static volatile boolean flag=true;   

    public static void main(String[] args) throws InterruptedException {
        Thread thread=new Thread(()->{
            while (flag){
                System.out.println("hello thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });

        thread.start();
        Thread.sleep(3000);
        flag=false;       //通过标志位 使线程中断结束
    }
}

示例-2:使用 Thread.interrupted() 或者 Thread.currentThread().isInterrupted() 代替自定义标志位.

Thread 内部包含了一个 boolean 类型的变量作为线程是否被中断的标记.

方法说明
public void interrupt()中断对象关联的线程,如果线程正在阻塞,则以异常方式通知,否则设置标志位
public static boolean interrupted()判断当前线程的中断标志位是否设置,调用后清除标志位
public boolean isInterrupted()判断对象关联的线程的标志位是否设置,调用后不清除标志位
  • 使用 thread 对象的 interrupted() 方法通知线程结束
//中断线程
public class ThreadDemo8 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread=new Thread(()->{
            while (!Thread.currentThread().isInterrupted()){
                System.out.println("hello thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
//                    try {
//                        Thread.sleep(500);
//                    } catch (InterruptedException ex) {
//                        ex.printStackTrace();
//                    }
                    break;
                }
            }
        });
        thread.start();
        Thread.sleep(3000);
        thread.interrupt();
    }
}

thread 收到通知的方式有两种:

  1. 如果线程因为调用 wait/join/sleep 等方法而阻塞挂起,则以 InterruptedException 异常的形式通知,清除中断标志

    • 当出现 InterruptedException 的时候, 要不要结束线程取决于 catch 中代码的写法. 可以选择忽略这个异常, 也可以跳出循环结束线程.
  2. 否则,只是内部的一个中断标志被设置,thread 可以通过

    • Thread.interrupted() 判断当前线程的中断标志被设置,清除中断标志
    • Thread.currentThread().isInterrupted() 判断指定线程的中断标志被设置,不清除中断标志

这种方式通知收到的更及时,即使线程正在sleep也可以马上收到

2.5 等待一个线程-join()

方法说明
public void join()等待线程结束
public void join(long millis)等待线程结束,最多等 millis 毫秒
public void join(long millis)同理,但可以更高精度
public class ThreadDemo {
    public static void main1(String[] args) {
        Thread thread=new Thread(()->{
            for (int i = 0; i <3 ; i++) {
                System.out.println("hello thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread.start();
        try {
            thread.join();    //让main线程等待thread线程结束,(等待t的run执行完)
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

2.6 获取当前线程

方法说明
public static Thread currentThread();返回当前线程对象的引用
public class ThreadDemo {
    public static void main(String[] args) {
        Thread thread = Thread.currentThread();
        System.out.println(thread.getName());
   }
}

2.7 休眠当前线程-sleep()

方法说明
public static void sleep(long millis) throws InterruptedException休眠当前线程 millis毫秒
public static void sleep(long millis, int nanos) throwsInterruptedException可以更高精度的休眠
public class ThreadDemo {
    public static void main(String[] args) throws InterruptedException {
        System.out.println(System.currentTimeMillis());
        Thread.sleep(3 * 1000);
        System.out.println(System.currentTimeMillis());
   }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值