多线程常用的几个方法汇总


最近学习并发编程遇到不少问题,就顺手总结了有关多线程的几个常用的方法

sleep()

sleep()方法属于Thread类,主要的作用是让当前线程停止执行,把cpu让给其他线程执行,但不会释放对象锁和监控的状态,到了指定时间后线程又会自动恢复运行状态

注意:线程睡眠到期自动苏醒,并返回到可运行状态,不是运行状态。sleep()中指定的时间是线程不会运行的最短时间。因此,sleep()方法不能保证该线程睡眠到期后就开始执行

  • 另外

    • Thread.sleep()方法是一个静态方法

    • Java有两种sleep方法,一个只有一个毫秒参数,另一个有毫秒和纳秒
      个参数第三代

sleep(long millis)

or

sleep(long millis, int nanos)

1//此try语句块放在run方法内
2try {
3            Thread.sleep(1000);
4       } catch (InterruptedException e) {
5            // TODO 自动生成的 catch 块
6            e.printStackTrace();
7       }

wait() notify()

wait()属于Object类,与sleep()的区别是当前线程会释放锁,进入等待此对象的等待锁定池。比方说,线程A调用Obj.wait(),线程A就会停止运行,而转为等待状态。至于等待多长时间? 那就看其他线程是否调用Obj.notify().其优势显而易见,成为多个线程之间进行通讯的有手段!

注意:它必须包含在Synchronzied语句中,无论是wait()还是notify()都需要首先获得目标的对象的一个监视器

  • 先来解释一下 "Synchronzied" 
    是一种同步锁。作用是实现线程间同步,对同步的代码加锁,使得每一次,只能有一线程进入同步块,从而保证线程间的安全性

它修饰的对象有以下几种:

  • 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的部分,进入同步代码前要获得给定对象的锁

  • 修饰一个实例方法,进入同步代码前要获得当前实例的锁

  • 修饰一个静态方法,进入同步代码前要获得当前类的锁

先给大家一个例子:

 1public class SimpleWN {
2    public static int count=0;
3    public static class one implements Runnable{
4        @Override
5        public void run() {
6            for (int i = 0; i < 100; i++) {
7                synchronized (this) {
8                    count++;
9                }
10            }                          
11        }  
12    }
13    public static void main(String[] args) throws InterruptedException {
14        Thread t1=new Thread(new one());
15        Thread t2=new Thread(new one());
16        t1.start();
17        t2.start();
18        t1.join();
19        t2.join();
20        System.out.println(count);
21    }
22}

不知道大家看出这段代码有一个严重错误。代码17,18行,两个线程实例的不是同一个对象,这也意味两个线程使用的是两把不同的锁,没法保证同步。多运行几次就会发现有时候结果并不是200

更正做法:

1    one oo=new one();
2    Thread t1=new Thread(oo);
3    Thread t2=new Thread(oo);

举例说明程序中应用wait() 和 notify():

 1public class SimpleWN {
2    final static Object object=new Object();
3    public static class one extends Thread{
4        @Override
5        public void run() {
6            synchronized (object) {
7                System.out.println("T1 开始");
8                try {
9                    System.out.println("T1 等待");
10                    object.wait();
11                } catch (InterruptedException e) {
12                    e.printStackTrace();
13                }
14                System.out.println("T1 结束");
15            }                  
16        }  
17    }
18    public static class two extends Thread{
19        @Override
20        public void run() {
21            synchronized (object) {
22                System.out.println("T2 开始");
23                System.out.println("释放一个线程");
24                object.notify();
25                System.out.println("T2 结束");
26            }                  
27        }  
28    }
29    public static void main(String[] args) throws InterruptedException {
30        Thread t1=new one();
31        Thread t2=new two();
32        t1.start();
33        t2.start();
34        t1.join();
35        t2.join();
36    }
37}

运行结果:

1T1 开始
2T1 等待
3T2 开始
4释放一个线程
5T2 结束
6T1 结束

join()

在某些情况下,子线程需要进行大量的耗时运算,主线程可能会在子线程执行结束之前结束,但是如果主线程又需要用到子线程的结果,换句话说,就是主线程需要在子线程执行之后再结束。这就需要用到join()方法

 1public class BigJoin {
2    public static int count;
3    public static class AddThread implements Runnable{
4        @Override
5        public void run() {
6            for (int i = 0; i < 1000000000; i++) {
7                count++;
8            }  
9        }  
10    }
11    public static void main(String[] args) throws InterruptedException {
12        // TODO 自动生成的方法存根
13        AddThread addThread=new AddThread();
14        Thread t1=new Thread(addThread);
15        t1.start();
16        t1.join();
17        System.out.println(count);
18    }
19}

yield()

中文意思:放弃,屈服
一个线程调用yield()意味着告诉虚拟机自己非常乐于助人,可以把自己的位置让给其他线程(这只是暗示,并不表绝对)。但得注意,让出cpu并不代表当前线程不执行了。当前线程让出cpu后,还会进行cpu资源的争夺,但是能不能再次分配到,就不一定了

 1public class SimpleYield extends Thread{
2    String name=null;
3    public  SimpleYield(String name) {
4        super(name);
5    }
6    @Override
7    public void run() {
8        // TODO 自动生成的方法存根
9        for(int i=1;i<=10;i++){
10            System.out.println(this.getName()+i);
11            if(i==5){
12                this.yield();
13            }
14        }
15    }
16    public static void main(String[] args) throws InterruptedException {
17        SimpleYield t1=new SimpleYield("小花");
18        SimpleYield t2=new SimpleYield("小草");
19        t1.start();
20        t2.start();
21    }
22}

运行结果:这只是其中一种结果,线程(小花)的执行到2时把cpu让给线程(小草)并执行,接下来-线程(小草)的执行到2时把cpu让给线程(小花)并执行

1小花1
2小花2
3小草1
4小草2
5小花3
6小花4
7小草3
8小草4

长按识别二维码关注


微信扫一扫
关注该公众号

  • 7
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Java面试资源概览 一、内容概览 本次分享的资源涵盖了Java面试的各个方面,从基础知识到高级技术,从数据库到框架应用,都做了深入的探讨和总结。具体内容包括: Java基础知识点:包括数据类型、面向对象特性、异常处理、集合框架等。 Java核心技术:如多线程、网络编程、序列化等都有详细的解释和示例。 常用框架:如Spring、MyBatis等框架的使用方法和内部原理都有涉及。 数据库相关:包括关系型数据库和非关系型数据库的使用,以及JDBC、MyBatis等与数据库交互的技术。 实战项目经验:分享了几个经典的Java项目,解析了项目的架构设计和核心技术点。 面试经验和技巧:整理了常见的Java面试问题,并给出了答题建议和技巧。 代码和项目实例:提供了多个Java项目的源代码,方便学习者参考和实践。 学习笔记和心得:记录了学习过程中的重点难点和心得体会,有助于学习者更好地理解和掌握知识。 二、适用人群 本资源适用于即将毕业或已经毕业,希望通过学习Java找到一份理想工作的同学。无论你是初学者还是有一定基础的开发者,都能从中获得启发和帮助。 三、使用建议 系统学习:建议学习者按照资源提供的顺序和内容,系统地学习和掌握Java的知识点。 实践为王:理论知识和实战经验相结合,通过实践来加深理解和记忆。 持续更新:由于Java技术和面试要求都在不断更新,建议学习者保持关注,随时更新自己的知识和技能。 交流与讨论:与同学或同行进行交流和讨论,分享学习心得和经验,共同进步。Java面试资源概览 一、内容概览 本次分享的资源涵盖了Java面试的各个方面,从基础知识到高级技术,从数据库到框架应用,都做了深入的探讨和总结。具体内容包括: Java基础知识点:包括数据类型、面向对象特性、异常处理、集合框架等。 Java核心技术:如多线程、网络编程、序列化等都有详细的解释和示例。 常用框架:如Spring、MyBatis等框架的使用方法和内部原理都有涉及。 数据库相关:包括关系型数据库和非关系型数据库的使用,以及JDBC、MyBatis等与数据库交互的技术。 实战项目经验:分享了几个经典的Java项目,解析了项目的架构设计和核心技术点。 面试经验和技巧:整理了常见的Java面试问题,并给出了答题建议和技巧。 代码和项目实例:提供了多个Java项目的源代码,方便学习者参考和实践。 学习笔记和心得:记录了学习过程中的重点难点和心得体会,有助于学习者更好地理解和掌握知识。 二、适用人群 本资源适用于即将毕业或已经毕业,希望通过学习Java找到一份理想工作的同学。无论你是初学者还是有一定基础的开发者,都能从中获得启发和帮助。 三、使用建议 系统学习:建议学习者按照资源提供的顺序和内容,系统地学习和掌握Java的知识点。 实践为王:理论知识和实战经验相结合,通过实践来加深理解和记忆。 持续更新:由于Java技术和面试要求都在不断更新,建议学习者保持关注,随时更新自己的知识和技能。 交流与讨论:与同学或同行进行交流和讨论,分享学习心得和经验,共同进步。Java面试资源概览 一、内容概览 本次分享的资源涵盖了Java面试的各个方面,从基础知识到高级技术,从数据库到框架应用,都做了深入的探讨和总结。具体内容包括: Java基础知识点:包括数据类型、面向对象特性、异常处理、集合框架等。 Java核心技术:如多线程、网络编程、序列化等都有详细的解释和示例。 常用框架:如Spring、MyBatis等框架的使用方法和内部原理都有涉及。 数据库相关:包括关系型数据库和非关系型数据库的使用,以及JDBC、MyBatis等与数据库交互的技术。 实战项目经验:分享了几个经典的Java项目,解析了项目的架构设计和核心技术点。 面试经验和技巧:整理了常见的Java面试问题,并给出了答题建议和技巧。 代码和项目实例:提供了多个Java项目的源代码,方便学习者参考和实践。 学习笔记和心得:记录了学习过程中的重点难点和心得体会,有助于学习者更好地理解和掌握知识。 二、适用人群 本资源适用于即将毕业或已经毕业,希望通过学习Java找到一份理想工作的同学。无论你是初学者还是有一定基础的开发者,都能从中获得启发和帮助。 三、使用建议 系统学习:建议学习者按照资源提供的顺序和内容,系统地学习和掌握Java的知识点。 实践为王:理论知识和实战经验相结合,通过实践来加深理解和记忆。 持续更新:由于Java技术和面试要求都在不断更新,建议学习者保持关注,随时更新自己的知识和技能。 交流与讨论:与同学或同行进行交流和讨论,分享学习心得和经验,共同进步。
Java中多线程常用方法有以下几种: 1. 继承Thread类:创建一个继承自Thread类的子类,并重写run()方法,在run()方法中定义线程要执行的任务。然后通过创建子类的对象,调用start()方法启动线程。 2. 实现Runnable接口:创建一个实现了Runnable接口的类,并实现其run()方法,在run()方法中定义线程要执行的任务。然后通过创建该类的对象,将其作为参数传递给Thread类的构造方法,再调用start()方法启动线程。 3. 使用Callable和Future:Callable接口是一种带有返回值的线程,通过实现Callable接口并实现其call()方法来定义线程要执行的任务。然后使用ExecutorService的submit()方法提交Callable任务,并返回一个Future对象,通过Future对象可以获取线程执行的结果。 4. 使用线程池:通过Executor框架提供的线程池来管理线程的创建和执行。可以使用Executors类提供的静态方法创建不同类型的线程池,然后将任务提交给线程池执行。 5. 使用synchronized关键字:通过在方法或代码块前加上synchronized关键字来实现线程同步,保证多个线程对共享资源的访问是互斥的。 6. 使用Lock接口:Lock接口提供了比synchronized更灵活和强大的线程同步机制。通过Lock接口的lock()和unlock()方法来实现对共享资源的加锁和解锁。 7. 使用wait()、notify()和notifyAll()方法:通过Object类提供的wait()、notify()和notifyAll()方法来实现线程间的通信和协作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值