首页 > 编程语言 >Java高级编程—多线程(完整详解线程的三种实现方式、以及守护线程、出让线程、插入线程、线程声明周期等,附有代码+案例)

Java高级编程—多线程(完整详解线程的三种实现方式、以及守护线程、出让线程、插入线程、线程声明周期等,附有代码+案例)

时间:2024-09-06 10:20:36浏览次数:13  
标签:Java Thread void t1 线程 new 多线程 public

二十八.多线程

文章目录

28.1线程的三种实现方式

  1. 继承Thread类的方式进行实现
  2. 实现Runnable接口的方式进行实现
  3. 利用Callable接口和Future接口方式实现

28.1.1 第一种

  • 继承Thread类的方式进行实现
1.自己定义一个类继承Thread
2.重写run方法,编写线程执行体
3.创建子类的对象,并用start()方法启动线程
public class Mythread extends Thread{
    @Override
    public void run() {
      //线程要执行代码
        for (int i = 0; i < 3; i++) {
            System.out.println(getName()+"你好");
        }
    }
}
==================================
public class MythreadTest {
    public static void main(String[] args) {

        Mythread t1 = new Mythread();
        Mythread t2 = new Mythread();

        t1.setName("线程1:");
        t2.setName("线程2:");

        t1.start();
        t2.start();
    }
}

28.1.2 第二种

  • 实现Runnable接口的方式进行实现

    1.自己定义一个类实现Runnable接口
    2.重写里面的run方法
    3.创建自己的类的对象
    4.创建一个Thread类的对象,并用start()方法开启线程

public class MyRun implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
          // 获取到当前线程的对象
            Thread t = Thread.currentThread();
            System.out.println(t.getName()+"你好a");
        }
    }
}
===================================================
  public class MyRunTest {
    public static void main(String[] args) {
      
        // 创建字节定义类的对象,表示要执行的任务
        ///即,创建线程要执行的参数对象
        MyRun m1 = new MyRun();

        // 创建线程对象
        Thread t1 = new Thread(m1);
        Thread t2 = new Thread(m1);
				//给线程设置名字
        t1.setName("线程1:");
        t2.setName("线程2:");
				//开启线程
        t1.start();
        t2.start();
    }
}

28.1.3 第三种

  • 利用Callable接口和Future接口方式实现

特点:可以获取到多线程运行的结果

1. 创建一个类MyCallable实现Callable接口
2. 重写call (是有返回值的,表示多线程运行的结果)
3. 创建MyCallable的对象(表示多线程要执行的任务)
4. 创建FutureTask的对象(作用管理多线程运行的结果)
5. 创建Thread类的对象,并启动(表示线程)
import java.util.concurrent.Callable;

public class MyCallable implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= 3; i++) {
            sum =sum +i;
        }
        return sum;
    }
}
===================================================
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class MyCallableTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        // 创建MyCallable的对象(表示多线程要执行的任务)
        MyCallable mc = new MyCallable();

        // 创建FutureTask的对象(作用管理多线程运行的结果)
        FutureTask<Integer> ft = new FutureTask<>(mc);

        // 创建线程对象
        Thread t1 = new Thread(ft);
        // 开启线程
        t1.start();

        // 获取多线程运行的结果
        Integer res = ft.get();
      
        System.out.println(res);
    }
}

28.2 常见的成员方法

方法说明
String getName()返回此线程的名称
void setName(String name)设置线程的名字(构造方法也可以设置名字)
static Thread currentThread()获取当前线程的对象
static void sleep(long time)让线程休眠指定的时间,单位为毫秒
setPriority(int newPriority)设置线程的优先级
final int getPriority()获取线程的优先级
final void setDaemon(boolean on)设置为守护线程
public static void yield()出让线程/礼让线程
public final void join()插入线程/插队线程
public class MyRun implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            // 获取到当前线程的对象
            Thread t = Thread.currentThread();
            try {
                //休眠多少时间
                t.sleep(5000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println(t.getName()+"你好a");
        }
    }
}
========================================
public class MyRunTest {
    public static void main(String[] args) throws InterruptedException {

        // 创建字节定义类的对象,表示要执行的任务
        // 创建线程要执行的参数对象
        MyRun m1 = new MyRun();

        // 创建线程对象
        Thread t1 = new Thread(m1);
        Thread t2 = new Thread(m1);
      
        Thread t3 = new Thread(m1,"线程3:");
      
       //给线程设置名字
        t1.setName("线程1:");
        t2.setName("线程2:");
      
      //获取优先级
      System.out.println(t1.getPriority());//5
      
      //设置优先级(默认是5)
      t1.setPriority(10);//可以先让t1线程先执行完

        // t1.sleep(5000);
        t1.start();
        t2.start();
        t3.start();
    }
}
//用构造方法设置线程名字
// 需要子类继承Thread,然后子类用super调用父类Thread的构造方法
public class Mythread extends Thread{
    public Mythread() {
    }

    public Mythread(String name) {
        super(name);
    }

    @Override
    public void run() {
        //线程要执行代码
        for (int i = 0; i < 3; i++) {
            System.out.println(getName()+"你好");
        }
    }
}
=============================================
public class MythreadTest {
    public static void main(String[] args) {

        Mythread  t1 = new Mythread("线程1:");
        Mythread t2 = new Mythread("线程2:");

        // t1.setName("线程1:");
        // t2.setName("线程2:");

        t1.start();
        t2.start();
    }
}

28.3 守护线程

final void setDaemon(boolean on)  设置为守护线程
当非守护线程执行结束后,守护线程才陆续结束;守护线程并不会立即结束
public class Mythread1  extends Thread{
    //非守护线程
    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            System.out.println(getName()+"better..."+i);
        }
    }
}
=============================================
  public class Mythread2 extends Thread{
    // 守护线程
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName()+"good..."+i);
        }
    }
}
=============================================
  public class MythreadTest {
    public static void main(String[] args) {

       //创建线程对象
        Mythread1 t1 = new Mythread1();
        Mythread2 t2 = new Mythread2();
        // 给线程设置名字
        t1.setName("大树");
        t2.setName("小草");

      // 将线程2设置为守护线程
     //即,当非守护线程1执行结束后,守护线程2才陆续结束,并不会立即结束
        t2.setDaemon(true);

        // 开启线程
        t1.start();
        t2.start();
    }
}

28.4 出让线程

public static void yield()   出让线程/礼让线程

当某线程1执行结束后,会让当前CPU的执行权,此时多个线程包括线程1会重新抢夺CPU的执行权,让运行的结果尽可能的均匀
public class Mythread1 extends Thread{
  
    public Mythread1() {}

    public Mythread1(String name) { super(name);}

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(getName()+"...");
            //设置为出让线程/礼让线程
            //表示出让当前CPU的执行权
            Thread.yield();
        }
    }
}
=============================================
  public class MyThreadTest {
    public static void main(String[] args) {

        Mythread1 t1 = new Mythread1("线程1:");
        Mythread1 t2 = new Mythread1("线程2:");

        t1.start();
        t2.start();

    }
}

28.5 插入线程

public final void join()          
插入线程/插队线程   表示插入当前线程之前
  
比如有线程1 和线程2, 在抢夺CPU的执行权,如果线程2抢到,线程2执行,如果将线程1设置为插入线程,则表示当线程1执行结束后,线程2 才会执行
public class MyThread  extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(getName()+"..."+i);
        }
    }
}
=============================================
public class MyThreaTest {
    public static void main(String[] args) throws InterruptedException {

        MyThread t1 = new MyThread();
        t1.setName("线程1:");
        t1.start();
        //表示把t1这个线程,插入到当前线程之前。
        //t1:线程1
        //当前线程: main线程
        t1.join();

        // 执行在main线程当中
        for (int i = 0; i < 10; i++) {
            System.out.println("man线程...");
        }
        
    }
}

28.6 线程生命周期

(图片来自B站Java视频)
在这里插入图片描述

问:sleep方法会让线程睡眠,睡眠时间结束后,立马会执行下面的代码么?

答:不会,因为睡眠结束后,会进入就绪状态,进行CPU的抢夺,抢到CPU 的执行权后才会进入运行状态。

28.7 同步代码块

把操作共享数据的代码锁起来

格式
  synchronized(锁){
      操作共享数据的代码
}

共有100张券,而有3个销售出售,请设计一个程序模拟该出售过程

public class MyThread extends Thread {
    // 表示这个类所有的对象,都共享ticket数据
    static int ticket=0;//0-99

    // 锁对象,一定是唯一的,即 表示obj被共享
    static Object obj = new Object();

    @Override
    public void run() {
        while (true) {
            // 同步代码块
           // obj 可换成 MyThread.class
            synchronized (obj) {
                if (ticket < 100) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    ticket++;
                    System.out.println(getName() + "出售第" +                      ticket + "个东西");
                } else {
                    break;
                }
            }
        }
    }
    // ending.....
}
==================================
  public class MyThreadTest {
    public static void main(String[] args) {

        // 创建线程对象
        MyThread t1= new MyThread();
        MyThread t2 = new MyThread();
        MyThread t3 = new MyThread();

        // 给线程设置名字
        t1.setName("A:");
        t2.setName("B:");
        t3.setName("C:");

        // 开启线程
        t1.start();
        t2.start();
        t3.start();
    }
}

28.8 同步方法

把synchronized关键字加到方法上

格式
修饰符 synchronized 返回值类型 方法名(方法参数){
  ....
}

特点:

  • 同步方法是锁住方法里的所有代码

  • 锁对象不能自己指定

    非静态 :this

    静态: 当前类的字节码文件对象

需求:

共有100张券,而有3个销售出售,请设计一个程序模拟该出售过程
利用同步方法完成
(技巧:先写成同步代码块,再改成成同步方法)

public class MyRunnable implements  Runnable{
    // 此处static可以省略不写
    //因为MyRunnable只创建了一次...
     static int stick =0;//0-99
    @Override
    public void run() {
        while (true){
                if (method()) break;
        }
    }
    //ctrl + alt +m ;抽取成方法
    //方法是非静态的,所以锁对象是this,指的是mr,mr是唯一的
    private  synchronized boolean method() {
        if (stick == 100){
            return true;
        }else {
            stick++;
            String name = Thread.currentThread().getName();
            System.out.println(name+"出售第"+stick+"个东西");
        }
        return false;
    }
}
==================================
  public class MyRunnableTest {
    public static void main(String[] args) {

			  //创建线程要执行的参数对象,即 任务
        MyRunnable mr = new MyRunnable();

        // 创建线程对象,(代表三个销售)
        Thread t1 = new Thread(mr);
        Thread t2 = new Thread(mr);
        Thread t3 = new Thread(mr);
				// 给线程设置名字
        t1.setName("A:");
        t2.setName("B:");
        t3.setName("C:");
				//开启线程
        t1.start();
        t2.start();
        t3.start();
    }
}

标签:Java,Thread,void,t1,线程,new,多线程,public
From: https://blog.csdn.net/weixin_54555405/article/details/141949321

相关文章

  • Java-IO:浅谈对NIO的认识
    Java-IO:简述常见的IO模型Java-IO:浅谈对IO的认识NIO即NewIO,这个库是在JDK1.4中才引入的。NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多。在JavaAPI中提供了两套NIO,一套是针对标准输入输出NIO,另一套就是网络编程NIO。一、NIO......
  • Java:集合的相关汇总介绍
    主要包含Set(集)、List(列表包含Queue)和Map(映射)。1、Collection:Collection是集合List、Set、Queue的最基本的接口。2、Iterator:迭代器,可以通过迭代器遍历集合中的数据。3、Map:是映射表的基础接口。一、List接口Java的List是非常常用的数据类型。List是有......
  • Java 虹软人脸识别SDK:基于虹软人脸识别SDK的Java项目集成指南
    基于虹软人脸识别SDK的Java项目集成指南虹软人脸识别SDK是一款功能全面且成熟的解决方案,广泛应用于智能设备、人脸识别门禁、身份验证等领域。集成虹软人脸识别SDK到Java项目中,可以实现高效的人脸检测、特征提取和比对功能,使得Java开发者能够在各类应用场景中快速部署人脸......
  • 基于Java的信息发布与管理系统设计与开发-计算机毕业设计源码+LW文档
    摘要在互联网高度发展的今天,人们已经习惯利用网络来填充生活中的碎片时间,如听歌、看视频、浏览信息等。然而,遇到喜欢的内容时,由于时间限制,可能无法一次性看完。此外,各种信息内容分布在不同的平台,给用户查找带来了不便。针对这一问题,Java的信息发布与管理系统应运而生,它有效地解决......
  • Java面试——基础篇
    基本数据类型与包装类基本数据类型与引用数据类型区别存储方式:基本数据类型直接存储值,而引用数据类型存储的是对象的引用(内存地址)内存分配:基本数据类型在栈上分配内存,引用数据类型在堆上分配内存(具体内容存放在堆中,栈中存放的是其具体内容所在内存的地址)。栈上的分配速度......
  • JavaWeb - Spring Boot - 请求参数
    @RequestMapping从注解名称上我们可以看到,@RequestMapping注解的作用就是将请求和处理请求的控制器方法关联起来,建立映射关系。SpringMVC接收到指定的请求,就会来找到在映射关系中对应的控制器方法来处理这个请求。@RequestMapping标识一个类:设置映射请求的请求路径的初始信......
  • Java工程师多年之后看指针
      指针是基本数据类型,占用4个字节。Int类型的数据计算机处理语言中是处中间层。使用图形化方式可以这样更形象直观。   计算机对二进制处理数据的方式比较敏感。现人们的大脑计数方式是通过十进制的方式计算日常和工作中需要的业务。操作符的限制,才增加了十六进制......
  • Java泛型-类型参数化
    一.泛型解决支持多类型参数的方案:1,重载:在同一个类中,方法名相同,参数不同不足之处:代码过于重复publicclassTool{  publicStringarrToStr(String[]arr,Stringsymbol){    Stringstr="";    for(Stringv:arr){      str+=s......
  • Java开发初学:认识Java的基本知识
    Java的基础知识等进行介绍Java的发展史与Java体系Java是sun(StanfordUniversityNetwork)公司,1982年成立,java的主要设计者是JamesGosling,来源一个为电子消费产品项目Green。95年,Sun发布JDK1.t098年,JDK1.2,更名为Java2后续JDK1.3、1.4JDK1.5,更名为Java5.0我们使用jdk1......
  • Java毕业设计基于SpringBoot的超市在线销售系统(源码+文档+调试+讲解)
    文末获取资源,收藏关注不迷路文章目录项目介绍技术介绍项目界面关键代码目录项目介绍该超市在线销售系统采用B/S架构、并采用java语言以及springboot框架进行开发。该系统主要设计并完成了管理过程中的用户注册登录、个人信息修改、用户、普通管理员、商品信息、留言......