【多线程】Thread类的用法

文章目录

    • [1. Thread类的创建](#1. Thread类的创建)
      • [1.1 自己创建类继承Thread类](#1.1 自己创建类继承Thread类)
      • [1.2 实现Runnable接口](#1.2 实现Runnable接口)
      • [1.3 使用匿名内部类创建Thread子类对象](#1.3 使用匿名内部类创建Thread子类对象)
      • [1.4 使用匿名内部类创建Runnable子类对象](#1.4 使用匿名内部类创建Runnable子类对象)
      • [1.5 使用lambda创建](#1.5 使用lambda创建)
    • [2. Thread常见的构造方法](#2. Thread常见的构造方法)
      • [2.1 Thread()](#2.1 Thread())
      • [2.2 Thread(Runnable target)](#2.2 Thread(Runnable target))
      • [2.3 Thread(String name)](#2.3 Thread(String name))
      • [2.4 Thread(Runnable target, String name)](#2.4 Thread(Runnable target, String name))
    • [3. Thread常见的属性](#3. Thread常见的属性)
    • [4. 线程的使用](#4. 线程的使用)
      • [4.1 启动线程](#4.1 启动线程)
      • [4.2 中断线程](#4.2 中断线程)
      • [4.3 等待线程](#4.3 等待线程)
      • [4.4 休眠线程](#4.4 休眠线程)

1. Thread类的创建

1.1 自己创建类继承Thread类

java 复制代码
package Thread;

//继承Thread类实现线程
class MyThread extends Thread{
    @Override
    public void run() {
            System.out.println("hello run");
    }
}
public class Dome1 {
    public static void main(String[] args){
    	//创建线程
        MyThread myThread = new MyThread();
        //启动线程
        myThread.start();
    }
}

1.2 实现Runnable接口

java 复制代码
//使用Runnable的方式创建线程
class MyRunnable implements Runnable{
    @Override
    public void run() {
            System.out.println("hello run");
    }
} 
public class Dome2 {
    public static void main(String[] args){
    	//创建线程
        MyRunnable myRunnable = new MyRunnable();
        Thread t = new Thread(myRunnable);
        //启动
        t.start();
    }
}

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

java 复制代码
//通过匿名内部类的方式创建线程
public class Dome3 {
    public static void main(String[] args) {
    	//创建线程
        Thread t = new Thread(){
            @Override
            public void run() {
                    System.out.println("hello run");
            }
        };
        //启动线程
        t.start();
    }
}

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

java 复制代码
//使用匿名内部类创建Runnable子类对象
public class Dome4 {
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                    System.out.println("hello run");
            }
        });
        t.start();
}

1.5 使用lambda创建

java 复制代码
//lambda实现线程
public class Dome5 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread( () -> {
                System.out.println("hello run");
        });
        t.start();
    }
}

2. Thread常见的构造方法

2.1 Thread()

java 复制代码
//创建Thread对象
Thread t = new Thread();

2.2 Thread(Runnable target)

java 复制代码
//使用Runnable对象创建线程对象
Thread t = new Thread(new Runnable);

2.3 Thread(String name)

java 复制代码
//为这个线程命名
Thread t = new Thread("名字");

2.4 Thread(Runnable target, String name)

java 复制代码
//使用Runnable对象创建线程对象并命名
Thraed t = new Thread(new Runnable,"名字");

3. Thread常见的属性

属性 获取方法
ID getId()
name getName()
状态 getState()
优先级 getPriority()
是否为后台线程 isDaemon()
是否存活 isAlive()
是否中断 isInterrupted()
java 复制代码
public class Test4 {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            //Thread.currentThread调用当前线程对象,相当于t,这个时候t还未初始化成功,不能直接使用
            System.out.println("ID: " + Thread.currentThread().getId());
            System.out.println("name: " + Thread.currentThread().getName());
            System.out.println("状态: " + Thread.currentThread().getState());
            System.out.println("优先级: " + Thread.currentThread().getPriority());
            System.out.println("是否为后台线程: "  + Thread.currentThread().isDaemon());
            System.out.println("是否存活: " + Thread.currentThread().isAlive());
            System.out.println("是否中断: " + Thread.currentThread().isInterrupted());
        });
        t.start();
    }
}

注意:

  1. ID 是线程的唯一标识,不同线程不会重复
  2. 名称是各种调试工具用到
  3. 状态表示线程当前所处的一个情况,下面我们会进一步说明
  4. 优先级高的线程理论上来说更容易被调度到
  5. 关于后台线程,需要记住一点:JVM会在一个进程的所有非后台线程结束后,才会结束运行。
  6. 是否存活,即简单的理解,为 run 方法是否运行结束了

4. 线程的使用

4.1 启动线程

前面我们已经知道了线程的创建,构造等方法,但这些其实都是准备工作,还没有真正的从底层创建出一个线程,只有调用start方法够才算真正的创建成功线程。
//直接调用就可以 t.start()

4.2 中断线程

当线程启动的时候,有时里面是循环,这时线程便不会停止,我们便要想办法中断线程。中断线程有个简单的方法直接使用Thread.stop()方法,但是,这种方法是unsafe,而且基本上已经deprecated。

所以我们调用interrupt()方法进行停止线程,但它并不会直接停止线程,而是对线程内进行标记,标记为Boolean类的true。这个时候我们再调用下面两个方法。
public static boolean interruputed();测试线程是否为中断状态,还执行后会标记清除为false。
public boolean isInterputed();测试线程是否为中断状态,但不清除标记。

添加标志符进行中断:

java 复制代码
//中断线程,添加标志位
public class Test3 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
        	//
           while(!Thread.currentThread().isInterrupted()){
               System.out.println(Thread.currentThread().getName());
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
//                   e.printStackTrace();
                   break;
               }
           }
        });
        //启动线程
        t1.start();
        //休眠3秒
        Thread.sleep(3000);
        t1.interrupt();
    }
}

注意:

如果休眠中中断线程,则会异常,反之,也是。

java 复制代码
//中断线程,添加标志位
public class Test3 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
//           while(!Thread.currentThread().isInterrupted()){
               try {
                   Thread.sleep(100000);
               } catch (InterruptedException e) {
                   e.printStackTrace();
                   System.out.println("异常!");
               }
//           }
            System.out.println("end!");
        });
        t1.start();
        Thread.sleep(3000);
        t1.interrupt();
        System.out.println(t1.isInterrupted());
        System.out.println(Thread.interrupted());
    }
}

4.3 等待线程

方法 说明
join() 等待线程结束
join(long millis) 等待线程结束,最多等待millis毫秒
join(long millis,int nanos) 和2相比更加的精确

当我们同时启动几个线程,由于线程启动时随机无序的,我们无法得知谁先结束,这个时候就可以使用join方法让线程等待。

例如:当我们想让张三先上班,等张三上班结束,李四接班,那么我们就可以写出下面代码。

java 复制代码
public class Test5 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()){
                System.out.println(Thread.currentThread().getName() + "在上班");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e ){
                    break;
                }
            }
        },"张三");
        Thread t2 = new Thread(() -> {
           while(!Thread.currentThread().isInterrupted()){
               System.out.println(Thread.currentThread().getName() + "在上班");
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   break;
               }
           }
        },"李四");
        System.out.println("监督张三");
        t1.start();
        Thread.sleep(3000);
        t1.interrupt();
        t1.join();
        System.out.println("监督李四");
        t2.start();
        Thread.sleep(3000);
        t2.interrupt();
        t2.join();
    }
}

4.4 休眠线程

线程在执行的时候是非常快的,这个时候我们就可以让线程执行一次后就休眠一定时间,便于更好的观察。

上面代码中我们也多次用到。

java 复制代码
Thread.sleep(long millis),里面millis单位是毫秒。
相关推荐
TangKenny8 分钟前
计算网络信号
java·算法·华为
肘击鸣的百k路9 分钟前
Java 代理模式详解
java·开发语言·代理模式
城南vision15 分钟前
Docker学习—Docker核心概念总结
java·学习·docker
wyh要好好学习23 分钟前
SpringMVC快速上手
java·spring
尢词25 分钟前
SpringMVC
java·spring·java-ee·tomcat·maven
Mr. zhihao31 分钟前
享元模式在 JDK 中的应用解析
java·享元模式
茶馆大橘35 分钟前
微服务系列五:避免雪崩问题的限流、隔离、熔断措施
java·jmeter·spring cloud·微服务·云原生·架构·sentinel
wrx繁星点点35 分钟前
享元模式:高效管理共享对象的设计模式
java·开发语言·spring·设计模式·maven·intellij-idea·享元模式
真的想不出名儿38 分钟前
Java基础——反射
java·开发语言
鱼跃鹰飞40 分钟前
大厂面试真题-简单说说线程池接到新任务之后的操作流程
java·jvm·面试