Java基础进阶线程中的常用方法

简介: Java基础进阶线程中的常用方法

一、获取线程的名字


String name = 线程对象.getName();

修改线程对象的名字

线程对象.setName("线程名字");

当线程没有设置名字的时候,默认的名字有什么规律?(了解一下)

   Thread-0

   Thread-1

   Thread-2

   Thread-3


二、获取当前线程对象


Thread t = Thread.currentThread();

返回值t就是当前线程。


示例代码01:


public class ThreadTest05 {
    public static void doSome(){
        //这样就不行了
        //this.getName();
        //super.getName();
        // 但是这样可以
        String name = Thread.currentThread().getName();
        System.out.println("-->" + name);
    }
    public static void main(String[] args) {
        //创建分支线程对象
        MyThread2 t1 = new MyThread2();
        //调用doSome方法()
        ThreadTest05.doSome();
        //获取当前的线程对象
        // currentThread就是当前线程对象
        // 这个代码出现在main方法当中,所以当前线程就是主线程。
        Thread currentThread = Thread.currentThread();
        System.out.println(currentThread.getName());
        //获取线程名字
        String n1 = t1.getName();
        System.out.println(n1);
        //修改线程名字
        t1.setName("tttt");
        System.out.println(t1.getName());
        //创建第二个多线程对象
        MyThread2 t2 = new MyThread2();
        System.out.println(t2.getName());
        t2.setName("ssss");
        System.out.println(t2.getName());
        t2.start();
        //启动线程
        t1.start();
    }
}
class MyThread2 extends Thread{
    public void run(){
        for(int i=0;i<100;i++){
            //当前线程对象
            Thread currentThread = Thread.currentThread();
            System.out.println(currentThread().getName() + "-->" + i);
        }
    }
}


运行结果:


0a2653c851af460fa595bd959398a8f1.png


三、线程的sleep方法


关于线程的sleep方法:


static void sleep(long millis)


1、静态方法:Thread.sleep(1000);

2、参数是毫秒

3、作用:让当前线程进入休眠,进入“阻塞状态”,放弃占有CPU时间片,让给其它线程使用。


这行代码出现在A线程中,A线程就会进入休眠。

这行代码出现在B线程中,B线程就会进入休眠。

4、Thread.sleep()方法,可以做到这种效果:


间隔特定的时间,去执行一段特定的代码,每隔多久执行一次。


示例代码02:


public class ThreadTest06 {
    public static void main(String[] args) {
        //sleep方法让当前线程休眠指定时间,此处休眠5秒
        /*try {
        // 让当前线程进入休眠,睡眠5秒
        // 当前线程是主线程!!!
            Thread.sleep(1000 * 5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("HelloWorld!");*/
        //此处每循环一次,就休眠一秒
        for(int i=0;i<10;i++){
            System.out.println(Thread.currentThread().getName() + "--->" + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


运行结果:


2d65d23f6d4748949b924e4057485923.png


四、sleep方法的面试题


分支线程调用sleep方法,会休眠分支线程吗?


示例代码03:


public class ThreadTest07 {
    public static void main(String[] args) {
        //多态
        Thread t= new MyThread3();
        //修改名字
        t.setName("t");
        //启动分支线程
        t.start();
        try {
            // 问题:这行代码会让线程t进入休眠状态吗?
            // 在执行的时候还是会转换成:Thread.sleep(1000 * 5);
            // 这行代码的作用是:让当前线程进入休眠,也就是说main线程进入休眠。
            // 这样代码出现在main方法中,main线程睡眠。
            t.sleep(1000 * 5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("HeloWorld!");
    }
}
class MyThread3 extends Thread{
    public void run(){
        for(int i=0;i<10;i++){
            System.out.println(Thread.currentThread().getName() + "--->" + i);
        }
    }
}


运行结果:


6de278e6d6694ce5bb08e7e842b7e74b.png


五、终止线程的休眠


sleep睡眠太久了,如果希望半道上醒来,你应该怎么办?也就是说怎么叫醒一个正在睡眠的线程??


注意:这个不是终断线程的执行,是终止线程的睡眠。


调用interrupt方法终止休眠的线程


示例代码04:


public class ThreadTest08 {
    public static void main(String[] args) {
        //创建线程接口实现类对象
        Thread t = new Thread(new MyRunnable2());
        t.setName("t");
        t.start();
        // 希望5秒之后,t线程醒来(5秒之后主线程手里的活儿干完了。)
        try {
            Thread.sleep(1000 * 5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 终断t线程的睡眠(这种终断睡眠的方式依靠了java的异常处理机制。)
        t.interrupt();// 干扰,一盆冷水过去!
    }
}
class MyRunnable2 implements Runnable{
    // 重点:run()当中的异常不能throws,只能try catch
    // 因为run()方法在父类中没有抛出任何异常,子类不能比父类抛出更多的异常。
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "---> begin");
        try {
            // 睡眠1年
            Thread.sleep(1000 * 60 * 60 * 24 * 365);
        } catch (InterruptedException e) {
            // 打印异常信息
            //e.printStackTrace();
//            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "---> end");
        // 调用doOther
        //doOther();
    }
    // 其它方法可以throws
    /*public void doOther() throws Exception{
    }*/
}


运行结果:


8ec4f2997fb246878c34ecd6d122b7c6.png


六、强行终止线程的执行


调用现成的stop方法(此方法已过时)


在java中怎么强行终止一个线程的执行。

这种方式存在很大的缺点:容易丢失数据。因为这种方式是直接将线程杀死了,

线程没有保存的数据将会丢失。不建议使用。


示例代码05:


public class ThreadTest09 {
    public static void main(String[] args) {
        Thread t = new Thread(new MyRunnable3());//出错点,看清构造器中的实现类,别写错
        t.setName("t");
        t.start();
        //模拟5秒,设置5秒终止
        try {
            Thread.sleep(1000 * 5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //强制终止线程t//5秒后强制终止线程
        t.stop();//已过时
    }
}
class MyRunnable3 implements Runnable{
    @Override
    public void run() {
        for(int i=0;i<10;i++){
            System.out.println(Thread.currentThread().getName() + "--->" + i);
            //休眠一秒
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


运行结果:


12c3b7f3f8814309a195c64f051d4445.png


七、合理的终止一个线程的方法


使用if()循环的Return方法合理终止一个线程


示例代码06:


public class ThreadTest10 {
    public static void main(String[] args) {
        MyRunnable4 m = new MyRunnable4();
        Thread t = new Thread(m);
        t.setName("t");
        t.start();
        //模拟5秒
        try {
            Thread.sleep(1000 * 5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //当5秒后把线程休眠标记设置为false,线程终止,不会导致数据丢失
        m.run = false;
    }
}
class MyRunnable4 implements Runnable{
    //定义线程休眠标记
    boolean run = true;
    @Override
    public void run() {
       for(int i=0;i<10;i++){
           if(run){
               System.out.println(Thread.currentThread().getName() + "--->" + i);
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }else{
               // return就结束了,你在结束之前还有什么没保存的。
               // 在这里可以保存呀。
               //save....
               //终止当前线程
               return;
           }
       }
    }


运行结果:


34e8d716411043c08c7ffba9fbba23de.png


八、线程调度概述


常见的线程调度模型有哪些?


1、抢占式调度模型:


那个线程的优先级比较高,抢到的CPU时间片的概率就高一些/多一些。

java采用的就是抢占式调度模型。

2、均分式调度模型:


平均分配CPU时间片。每个线程占有的CPU时间片时间长度一样。

平均分配,一切平等。

有一些编程语言,线程调度模型采用的是这种方式。

3、线程调度的方法


实例方法:


void setPriority(int newPriority) 设置线程的优先级

int getPriority() 获取线程优先级

最低优先级1

默认优先级是5

最高优先级10

优先级比较高的获取CPU时间片可能会多一些。(但也不完全是,大概率是多的。)


示例代码07:


public class ThreadTest11 {
    public static void main(String[] args) {
        System.out.println("线程的最高优先级:" + Thread.MAX_PRIORITY);
        System.out.println("线程的最低优先级:" + Thread.MIN_PRIORITY);
        System.out.println("线程的默认优先级:" + Thread.NORM_PRIORITY);
        Thread.currentThread().setPriority(1);
        System.out.println(Thread.currentThread().getPriority());
        // main线程的默认优先级是:5
        //System.out.println(currentThread.getName() + "线程的默认优先级是:" + currentThread.getPriority());
        Thread t = new Thread(new MyRunnable5());
        t.setPriority(10);
        t.setName("t");
        t.start();
        // 优先级较高的,只是抢到的CPU时间片相对多一些。
        // 大概率方向更偏向于优先级比较高的。
        for(int i=0;i<10;i++){
            System.out.println(Thread.currentThread().getName() + "--->" + i);
        }
    }
}
class MyRunnable5 implements Runnable{
    public void run(){
        // 获取线程优先级
        //System.out.println(Thread.currentThread().getName() + "线程的默认优先级:" + Thread.currentThread().getPriority());
        for(int i=0;i<10;i++){
            System.out.println(Thread.currentThread().getName() + "--->" + i);
        }
    }
}


运行结果:


92ba0822ed0b46e1ae72df8a17d3a45b.png


九、线程让位


让位,当前线程暂停,回到就绪状态,让给其它线程。


静态方法:


static void yield() 让位方法

暂停当前正在执行的线程对象,并执行其他线程

yield()方法不是阻塞方法。让当前线程让位,让给其它线程使用。

yield()方法的执行会让当前线程从“运行状态”回到“就绪状态”。

注意:在回到就绪之后,有可能还会再次抢到。


示例代码08:


public class ThreadTest12 {
    public static void main(String[] args) {
        Thread t = new Thread(new MyRunnable6());
        t.setName("t");
        t.start();
        for(int i=1;i<1000;i++){
            System.out.println(Thread.currentThread().getName() + "--->" + i);
        }
    }
}
class MyRunnable6 implements Runnable{
    @Override
    public void run() {
        for(int i=1;i<1000;i++){
            //每100个让位一次。
            if(i % 100 == 0){
                Thread.yield();// 当前线程暂停一下,让给主线程。v
            }
            System.out.println(Thread.currentThread().getName() + "--->" + i);
        }
    }
}


运行结果:


d79b274929334152a6d38be91e2d1be3.png


十、线程合并


实例方法:void join()


示例代码09:


public class ThreadTest13 {
    public static void main(String[] args) {
        System.out.println("main ---> begin!");
        Thread t = new Thread(new MyRunnable7());
        t.setName("t");
        t.start();
        //合并线程
        try {
            t.join();//t合并到当前线程中,当前线程受阻塞,t线程执行直到结束
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("main ---> over");
    }
}
class MyRunnable7 implements Runnable{
    @Override
    public void run() {
        for(int i=0;i<1000;i++){
            System.out.println(Thread.currentThread().getName() + "--->" + i);
        }
    }
}


运行结果:

dfc80ca9d8004e6c9ddc00e8448ffc6a.png

相关文章
|
20天前
|
Java 开发者
Java多线程编程中的常见误区与最佳实践####
本文深入剖析了Java多线程编程中开发者常遇到的几个典型误区,如对`start()`与`run()`方法的混淆使用、忽视线程安全问题、错误处理未同步的共享变量等,并针对这些问题提出了具体的解决方案和最佳实践。通过实例代码对比,直观展示了正确与错误的实现方式,旨在帮助读者构建更加健壮、高效的多线程应用程序。 ####
|
11天前
|
缓存 Java 开发者
Java多线程编程的陷阱与最佳实践####
本文深入探讨了Java多线程编程中常见的陷阱,如竞态条件、死锁和内存一致性错误,并提供了实用的避免策略。通过分析典型错误案例,本文旨在帮助开发者更好地理解和掌握多线程环境下的编程技巧,从而提升并发程序的稳定性和性能。 ####
|
6天前
|
监控 Java 开发者
深入理解Java中的线程池实现原理及其性能优化####
本文旨在揭示Java中线程池的核心工作机制,通过剖析其背后的设计思想与实现细节,为读者提供一份详尽的线程池性能优化指南。不同于传统的技术教程,本文将采用一种互动式探索的方式,带领大家从理论到实践,逐步揭开线程池高效管理线程资源的奥秘。无论你是Java并发编程的初学者,还是寻求性能调优技巧的资深开发者,都能在本文中找到有价值的内容。 ####
|
11天前
|
安全 Java 开发者
Java中的多线程编程:从基础到实践
本文深入探讨了Java多线程编程的核心概念和实践技巧,旨在帮助读者理解多线程的工作原理,掌握线程的创建、管理和同步机制。通过具体示例和最佳实践,本文展示了如何在Java应用中有效地利用多线程技术,提高程序性能和响应速度。
41 1
|
12天前
|
Java 数据处理 数据安全/隐私保护
Java处理数据接口方法
Java处理数据接口方法
20 1
|
19天前
|
安全 Java 开发者
Java 多线程并发控制:深入理解与实战应用
《Java多线程并发控制:深入理解与实战应用》一书详细解析了Java多线程编程的核心概念、并发控制技术及其实战技巧,适合Java开发者深入学习和实践参考。
40 6
|
19天前
|
Java 开发者
Java多线程编程的艺术与实践####
本文深入探讨了Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的技术文档,本文以实战为导向,通过生动的实例和详尽的代码解析,引领读者领略多线程编程的魅力,掌握其在提升应用性能、优化资源利用方面的关键作用。无论你是Java初学者还是有一定经验的开发者,本文都将为你打开多线程编程的新视角。 ####
|
18天前
|
存储 安全 Java
Java多线程编程中的并发容器:深入解析与实战应用####
在本文中,我们将探讨Java多线程编程中的一个核心话题——并发容器。不同于传统单一线程环境下的数据结构,并发容器专为多线程场景设计,确保数据访问的线程安全性和高效性。我们将从基础概念出发,逐步深入到`java.util.concurrent`包下的核心并发容器实现,如`ConcurrentHashMap`、`CopyOnWriteArrayList`以及`BlockingQueue`等,通过实例代码演示其使用方法,并分析它们背后的设计原理与适用场景。无论你是Java并发编程的初学者还是希望深化理解的开发者,本文都将为你提供有价值的见解与实践指导。 --- ####
|
Java
JAVA方法的定义
JAVA方法的定义
94 0
|
6月前
|
安全 Java 编译器
杭州 【Java基础知识 11】java泛型方法的定义和使用(学习+改进+自己理解,想法) (借鉴-侵-删)
杭州 【Java基础知识 11】java泛型方法的定义和使用(学习+改进+自己理解,想法) (借鉴-侵-删)
43 1