Java基础之多线程详解

举报
小小张自由--张有博 发表于 2021/11/22 23:25:39 2021/11/22
【摘要】   Java基础之多线程详解 Thread类 构造方法:   常用方法: 创建并启动多线程的步骤 一、使用基类Thread 二、使用Runnable接口 三、使用匿名内部类 解决线程安全问题 一、同步代码块 二、同步方法 三、锁(Lock)机制 线程之间的...
 

Java多线程是抢占式,谁的优先级高,谁就先执行。

Java使用 java.lang.Thread 类代表线程,所有的线程对象都必须是Thread类或其子类的实例。

Thread类

构造方法:  

public Thread() :分配一个新的线程对象。

public Thread(String name) :分配一个指定名字的新的线程对象。

public Thread(Runnable target) :分配一个带有指定目标新的线程对象。

public Thread(Runnable target,String name) :分配一个带有指定目标新的线程对象并指定名字。

常用方法:

public String getName() :获取当前线程名称。

public void start() :导致此线程开始执行; Java虚拟机调用此线程的run方法。

public void run() :此线程要执行的任务在此处定义代码。

public static void sleep(long millis) :使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)。

public static Thread currentThread() :返回对当前正在执行的线程对象的引用。

public  void Join()    终止该线程

创建并启动多线程的步骤

一、使用基类Thread

1. 定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把 run()方法称为线程执行体。

2. 创建Thread子类的实例,即创建了线程对象

3. 调用线程对象的start()方法来启动该线程


  
  1. public class MyThread extends Thread{
  2. @Override
  3. public void run() {
  4. for( int i = 0;i < 20;i++){
  5. System.out.println("run"+i);
  6. }
  7. }
  8. }
  9. public static void main (String[]args){
  10. //多线程
  11. MyThread my1 = new MyThread();
  12. //my1.run();调用run()方法 单线程
  13. my1.start();//执行run()方法 多线程 新开一个栈空间
  14. //main执行
  15. for(int i = 0;i < 20;i++){
  16. System.out.println("main"+i);
  17. }
  18. }

二、使用Runnable接口

1. 定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。

2. 创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。

3. 调用线程对象的start()方法来启动线程


  
  1. public class DemoRunnableImpl implements Runnable{//步骤一
  2. @Override
  3. public void run(){
  4. for(int i = 0;i < 5;i++){
  5. System.out.println(Thread.currentThread().getName()+"-->"+i);
  6. }
  7. }
  8. }
  9. public static void main (String[] args){
  10. DemoRunnableImpl demo =new DemoRunnableImpl();//步骤二
  11. Thread thread= new Thread (demo);
  12. thread.start();//步骤三
  13. }

三、使用匿名内部类


  
  1. public static void main(String[] args){
  2. //线程的父类是Thread
  3. new Thread(){
  4. @Override
  5. public void run(){
  6. for(int i = 0;i < 5;i++){
  7. System.out.println(Thread.currentThread().getName()+"小小张自由");
  8. }
  9. }
  10. }.start();
  11. //线程的接口是Runnable
  12. Runnable r = new Runnable(){
  13. @Override
  14. public void run(){
  15. for(int i = 0;i < 5;i++){
  16. System.out.println(Thread.currentThread().getName()+"身体健康");
  17. }
  18. }
  19. };
  20. new Thread(r).start();
  21. }

解决线程安全问题

线程安全问题都是由全局变量及静态变量引起的。若每个线程中对全局变量、静态变量只有读操作,而无操作,一般来说,这个全局变量是线程安全的。

若有多个线程同时执行写操作,一般都需要考虑线程同步, 否则的话就可能影响线程安全。

synchronized 关键字可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。

锁对象 可以是任意类型。多个线程对象,要使用同一把锁。在任何时候,最多运行一个线程拥有同步锁,谁拿到锁就进入代码块,其他线程只能等待。

一、同步代码块


  
  1. //语法格式
  2. synchronized(同步锁){
  3. //需要同步操作的代码
  4. }
  5. //示例
  6. private int cont = 100;
  7. Object obj = new Object();
  8. @Override
  9. public void run(){
  10. synchronized(obj){ //被锁住的代码
  11. while(cont>0){
  12. //线程休眠10毫秒
  13. try{
  14. Thread.sleep(10);
  15. }catch(Exceptione){
  16. System.out.println(e.getMessage());
  17. }
  18. System.out.println(Thread.currentThread().getName()+"正在抢第"+cont+"票");
  19. cont--;
  20. }
  21. }
  22. }

二、同步方法

将需要同步操作的代码,抽出来。放到一个方法中。Run()方法再调用同步方法


  
  1. public synchronized void method(){
  2. //可能会产生线程安全问题的代码
  3. }

三、锁(Lock)机制

     1.在成员位置创建一个ReentrantLock对象

     2.在可能出现安全问题的代码前调用Lock接口中的方法Lock获取锁

     3.在可能出现安全问题的代码后调用Lock接口中的方法unLock释放锁


  
  1. public class DemoRunnableImpl implements Runnable {
  2. private int cont = 100;
  3. Lock lock=new ReentrantLock();//创建一个ReentrantLock对象
  4. @Override
  5. public void run() {
  6. lock.lock();//获取锁
  7. while (cont > 0) {
  8. //线程休眠10毫秒
  9. try {
  10. Thread.sleep(10);
  11. } catch (Exception e) {
  12. System.out.println(e.getMessage());
  13. }
  14. System.out.println(Thread.currentThread().getName() + "正在抢第" + cont + "票");
  15. cont--;
  16. }
  17. lock.unlock();//释放锁
  18. }
  19. }

线程之间的通信

    多个线程并发执行时, 在默认情况下CPU是随机切换线程的,当我们需要多个线程来共同完成一件任务,并且我们希望他们有规律的执行, 那么多线程之间需要一些协调通信,以此来帮我们达到多线程共同操作一份数据。

线程状态概述

 等待和唤醒案例——生产者和消费者

        1.顾客和老板线程必须使用同步代码块包裹起来,保证等待和唤醒只能有一个在执行

        2.同步使用的锁对象必须保证唯一

        3.只有锁对象才能能用wait()notify()方法


  
  1. public static void main(String[] args) {
  2. Object obj=new Object();//锁对象
  3. //消费者
  4. new Thread(){
  5. @Override
  6. public void run() {
  7. while (true){
  8. synchronized (obj){ //同步代码段
  9. System.out.println("告知老板要的包子种类和数量");
  10. try {
  11. obj.wait();//线程等待
  12. } catch (InterruptedException e) {
  13. e.printStackTrace();
  14. }
  15. //唤醒之后执行的代码
  16. System.out.println("包子已经做好了,开吃!");
  17. }
  18. }
  19. }
  20. }.start();
  21. //生产者
  22. new Thread(){
  23. @Override
  24. public void run() {
  25. while (true){
  26. try {
  27. Thread.sleep(5000); //花5s做包子
  28. } catch (InterruptedException e) {
  29. e.printStackTrace();
  30. }
  31. synchronized (obj){ //同步代码段
  32. System.out.println("老板5秒钟包子做好了,可以吃包子了!");
  33. //做好包子,调用notify方法,唤醒顾客吃包子
  34. obj.notify();
  35. System.out.println("---------------------");
  36. }
  37. }
  38. }
  39. }.start();
  40. }

 创作不易,如果本篇博客对您有一定的帮助,大家记得留言+点赞哦。

文章来源: blog.csdn.net,作者:小小张自由—>张有博,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/promsing/article/details/112408018

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。