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

相关文章
|
4天前
|
Java
Java—多线程实现生产消费者
本文介绍了多线程实现生产消费者模式的三个版本。Version1包含四个类:`Producer`(生产者)、`Consumer`(消费者)、`Resource`(公共资源)和`TestMain`(测试类)。通过`synchronized`和`wait/notify`机制控制线程同步,但存在多个生产者或消费者时可能出现多次生产和消费的问题。 Version2将`if`改为`while`,解决了多次生产和消费的问题,但仍可能因`notify()`随机唤醒线程而导致死锁。因此,引入了`notifyAll()`来唤醒所有等待线程,但这会带来性能问题。
Java—多线程实现生产消费者
|
6天前
|
安全 Java Kotlin
Java多线程——synchronized、volatile 保障可见性
Java多线程中,`synchronized` 和 `volatile` 关键字用于保障可见性。`synchronized` 保证原子性、可见性和有序性,通过锁机制确保线程安全;`volatile` 仅保证可见性和有序性,不保证原子性。代码示例展示了如何使用 `synchronized` 和 `volatile` 解决主线程无法感知子线程修改共享变量的问题。总结:`volatile` 确保不同线程对共享变量操作的可见性,使一个线程修改后,其他线程能立即看到最新值。
|
6天前
|
消息中间件 缓存 安全
Java多线程是什么
Java多线程简介:本文介绍了Java中常见的线程池类型,包括`newCachedThreadPool`(适用于短期异步任务)、`newFixedThreadPool`(适用于固定数量的长期任务)、`newScheduledThreadPool`(支持定时和周期性任务)以及`newSingleThreadExecutor`(保证任务顺序执行)。同时,文章还讲解了Java中的锁机制,如`synchronized`关键字、CAS操作及其实现方式,并详细描述了可重入锁`ReentrantLock`和读写锁`ReadWriteLock`的工作原理与应用场景。
|
6天前
|
安全 Java 编译器
深入理解Java中synchronized三种使用方式:助您写出线程安全的代码
`synchronized` 是 Java 中的关键字,用于实现线程同步,确保多个线程互斥访问共享资源。它通过内置的监视器锁机制,防止多个线程同时执行被 `synchronized` 修饰的方法或代码块。`synchronized` 可以修饰非静态方法、静态方法和代码块,分别锁定实例对象、类对象或指定的对象。其底层原理基于 JVM 的指令和对象的监视器,JDK 1.6 后引入了偏向锁、轻量级锁等优化措施,提高了性能。
22 3
|
6天前
|
存储 安全 Java
Java多线程编程秘籍:各种方案一网打尽,不要错过!
Java 中实现多线程的方式主要有四种:继承 Thread 类、实现 Runnable 接口、实现 Callable 接口和使用线程池。每种方式各有优缺点,适用于不同的场景。继承 Thread 类最简单,实现 Runnable 接口更灵活,Callable 接口支持返回结果,线程池则便于管理和复用线程。实际应用中可根据需求选择合适的方式。此外,还介绍了多线程相关的常见面试问题及答案,涵盖线程概念、线程安全、线程池等知识点。
70 2
|
14天前
|
安全 Java API
java如何请求接口然后终止某个线程
通过本文的介绍,您应该能够理解如何在Java中请求接口并根据返回结果终止某个线程。合理使用标志位或 `interrupt`方法可以确保线程的安全终止,而处理好网络请求中的各种异常情况,可以提高程序的稳定性和可靠性。
46 6
|
4天前
|
缓存 安全 Java
【JavaEE】——单例模式引起的多线程安全问题:“饿汉/懒汉”模式,及解决思路和方法(面试高频)
单例模式下,“饿汉模式”,“懒汉模式”,单例模式下引起的线程安全问题,解锁思路和解决方法
|
4天前
|
Java 程序员 调度
【JavaEE】线程创建和终止,Thread类方法,变量捕获(7000字长文)
创建线程的五种方式,Thread常见方法(守护进程.setDaemon() ,isAlive),start和run方法的区别,如何提前终止一个线程,标志位,isinterrupted,变量捕获
|
6天前
|
NoSQL Redis
单线程传奇Redis,为何引入多线程?
Redis 4.0 引入多线程支持,主要用于后台对象删除、处理阻塞命令和网络 I/O 等操作,以提高并发性和性能。尽管如此,Redis 仍保留单线程执行模型处理客户端请求,确保高效性和简单性。多线程仅用于优化后台任务,如异步删除过期对象和分担读写操作,从而提升整体性能。
23 1
|
2月前
|
存储 消息中间件 资源调度
C++ 多线程之初识多线程
这篇文章介绍了C++多线程的基本概念,包括进程和线程的定义、并发的实现方式,以及如何在C++中创建和管理线程,包括使用`std::thread`库、线程的join和detach方法,并通过示例代码展示了如何创建和使用多线程。
60 1