吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 637|回复: 7
收起左侧

[学习记录] java多线程知识实例代码及结果描述

[复制链接]
jayqia 发表于 2023-7-5 22:43

[md]Java提供了3种多线程的创建方式:

   (1)继承javal.ang包中的Thread类,重写 Thread类的run()方法,在run()方法中实现多线程代码。

   (2)实现javal.ang.Runnable接口,在run()方法中实现多线程代码。

   (3)实现java.util.concurrent.Callable接口,重写call()方法,并使用 Future接口获取call()方法返回的结果。

  案例1:运行下面的程序,分析输出结果

  ```java
package cn.edu.ahut.p13;
public class Example01 {

    public static void main(String[] args) {

        MyThread01 myThread = new MyThread01(); // 创建MyThread01实例对象

        myThread.run();           // 调用MyThread01类的run()方法

        while (true) {             // 该循环是一个死循环,打印输出语句

            System.out.println("Main方法在运行");

        }

    }

}

class MyThread01 {

    public void run() {

        while (true) {             // 该循环是一个死循环,打印输出语句

            System.out.println("MyThread类的run()方法在运行");

        }

    }

}
  ```

运行截图;
![](C:\Users\jay-qiao\AppData\Roaming\Typora\typora-user-images\image-20230509180914044.png)

根据代码分析,结果会是无限循环地打印两行信息:

"MyThread类的run()方法在运行"
"Main方法在运行"

这是因为在`main`方法中,首先创建了一个`MyThread01`的实例对象`myThread`,然后调用了`myThread.run()`方法。但是需要注意的是,`myThread.run()`并不会创建一个新的线程来执行`MyThread01`类中的代码,而是直接在当前的主线程上执行。因此,`MyThread01`类的`run()`方法会一直循环打印信息"MyThread类的run()方法在运行"。

同时,在`main`方法中,存在一个无限循环的`while`循环,不会停止执行。在每次循环中,会打印信息"Main方法在运行"。

因此,程序会无限循环地交替打印这两行信息,直到程序被手动终止。



​     Thread类

   为了实现多线程,Java提供了一个线程类Thread,通过继承Thread类,并重写Thread类中的run()方法便可实现多线程。在Thread类中提供了一个start()方法用于启动新线程,新线程启动后,JVM会自动调用run()方法,如果子类重写了run()方法便会执行子类中的run()方法。

   案例2:Thread类实现多线程

```java
package cn.edu.ahut.p13;

public class Example02 {
    public static void main(String[] args) {
        MyThread02 myThread = new MyThread02(); // 创建MyThread02的线程对象
        myThread.start(); // 开启线程
        while (true) { // 通过死循环语句打印输出
            System.out.println("main()方法在运行");
        }
    }
}

class MyThread02 extends Thread {
    public void run() {
        while (true) { // 通过死循环语句打印输出
            System.out.println("MyThread类的run()方法在运行");

        }
    }
}
```

运行截图;

![](C:\Users\jay-qiao\AppData\Roaming\Typora\typora-user-images\image-20230509181508403.png)

代码中有两个线程:主线程(main)和自定义线程(MyThread02)。主线程和自定义线程都通过死循环语句打印输出。

当程序运行时,主线程首先创建并启动了自定义线程对象myThread。然后,主线程进入一个无限循环,在循环内部打印输出"main()方法在运行"。同时,自定义线程对象myThread也进入一个无限循环,在循环内部打印输出"MyThread类的run()方法在运行"。

因为两个线程都是无限循环的,所以会一直执行打印输出语句。输出结果将交替出现,没有固定的顺序。可能的输出结果是:

```
main()方法在运行
MyThread类的run()方法在运行
main()方法在运行
MyThread类的run()方法在运行
...
```

由于两个线程都在不断地执行循环体,没有终止条件,所以程序将一直运行下去。这是一个典型的多线程并发执行的例子。



Runnable接口

   继承Thread类实现多线程的弊端

​    因为Java只支持单继承,一个类一旦继承了某个父类就无法再继承Thread类,比如学生类Student继承了Person类,那么Student类就无法再通过继承Thread类创建线程

   Thread类提供了另外一个构造方法Thread(Runnable target),其中参数类型Runnable是一个接口,它只有一个run()方法。当通过Thread(Runnable target)构造方法创建线程对象时,只需为该方法传递一个实现了Runnable接口的对象,这样创建的线程将实现了Runnable接口中的run()方法作为运行代码,而不需要调用Thread类中的run()方法。

   案例3:通过实现Runnable接口的方式来创建多线程

```{java}
package cn.edu.ahut.p13;

class MyThread03 implements Runnable {
    public void run() {// 线程的代码段,当调用start()方法时,线程从此处开始执行
        while (true) {
            System.out.println("MyThread类的run()方法在运行");
        }
    }
}

public class Example03 {
    public static void main(String[] args) {
        MyThread03 myThread = new MyThread03(); // 创建MyThread03的实例对象
        Thread thread = new Thread(myThread);  // 创建线程对象
        thread.start();     // 开启线程,执行线程中的run()方法
        while (true) {
            System.out.println("main()方法在运行");
        }
    }
}
```

该代码创建了一个实现了Runnable接口的线程类MyThread03,并在其中实现了run()方法。在run()方法中,使用一个无限循环来输出"MyThread类的run()方法在运行"。

在Example03的main()方法中,首先创建了MyThread03的实例对象myThread,然后通过该实例对象创建了一个Thread对象thread。接下来调用thread的start()方法来启动线程,从而执行线程中的run()方法。

在启动线程后,主线程继续执行while循环,输出"main()方法在运行"。由于主线程和MyThread03线程是并行执行的,因此两个循环的输出会交替进行。

然而,由于MyThread03的run()方法中使用了一个无限循环,线程不会自动结束。因此,无论是主线程还是MyThread03线程,都会一直输出相应的内容,程序不会停止。

因此,运行该代码会不断交替输出"main()方法在运行"和"MyThread类的run()方法在运行",并且程序不会停止,需要手动终止程序。





运行结果:

![](C:\Users\jay-qiao\AppData\Roaming\Typora\typora-user-images\image-20230509181942794.png)





实现Callable接口

   通过Thread类和Runnable接口实现多线程时,需要重写run()方法,但是由于run()方法没有返回值,因此无法从新线程中获取返回结果。为了解决这个问题,Java提供了一个Callable接口,来满足这种既能创建新线程又可以有返回值的需求。

   Callable接口的方式创建线程步骤

​    (1)创建一个Callable接口的实现类,同时重写Callable接口的call()方法。

​    (2)创建Callable接口的实现类对象。

​    (3)通过FutureTask线程结果处理类的有参构造方法封装Callable接口实现类对象。

​    (4)调用参数为FutureTask类对象的Thread有参构造方法创建Thread线程实例。

​    (5)调用线程实例的start()方法启动线程。

   示例:通过实现Callable接口的方式来创建多线程

```java
package cn.edu.ahut.p13;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

class MyThread04 implements Callable<Object> {
    // 重写Callable接口的call()方法
    public Object call() throws Exception {
        int i = 0;
        while (i++ < 5) {
            System.out.println(Thread.currentThread().getName()
                    + "的call()方法在运行");
        }
        return i;
    }
}
public class Example04{
    public static void main(String[] args) throws InterruptedException, ExecutionException {

        MyThread04 myThread = new MyThread04(); // 创建Callable接口的实例对象
        //使用FutureTask封装MyThread04类
        FutureTask<Object> ft1 = new FutureTask<>(myThread);
        //使用Thread(Runnable target ,String name)构造方法创建线程对象
        Thread thread1 = new Thread(ft1, "thread");
        //调用线程对象的start()方法启动线程
        thread1.start();
        //通过FutureTask对象的方法管理返回值
        System.out.println(Thread.currentThread().getName()+ "的返回结果:"+ ft1.get());
        int a=0;
        while (a++<5) {
            System.out.println("main()方法在运行");
        }
    }
}
```

结果:

![image-20230509182619734](C:\Users\jay-qiao\AppData\Roaming\Typora\typora-user-images\image-20230509182619734.png)

分析:

给定的代码会先执行`MyThread04`的`call()`方法,然后才会执行`main()`方法。`call()`方法会打印五次线程名,而`main()`方法会打印五次"main()方法在运行"。由于使用了`FutureTask`,`main()`方法会等待`call()`方法执行完毕并获取其返回结果后才会继续执行





四、线程操作的相关方法

案例5:演示不同优先级的两个线程的运行情况

   步骤一:定义MaxPriority类并实现Runnable接口。在MaxPriority中,使用for循环打印正在发售的票数。代码如下所示:

步骤一:定义MaxPriority类并实现Runnable接口。在MaxPriority中,使用for循环打印正在发售的票数。代码如下所示:

```java
class MaxPriority implements Runnable {

     public void run() {

      for (int i = 0; i < 5; i++) {

      System.out.println(Thread.currentThread().getName() + "正在输出:" + i);

      }

     }

   }
```

  步骤二:定义MinPriority类并实现Runnable接口。在MinPriority中,使用for循环打印正在发售的票数。代码如下所示:

  

```java
    class MinPriority implements Runnable {

     public void run() {

      for (int i = 0; i < 5; i++) {

       System.out.println(Thread.currentThread().getName() + "正在输出:" + i);

      }

     }

    }
```

   步骤三:定义main()方法,创建两个线程,分别设置线程的优先级,然后开启线程。代码如下所示:

```java
public static void main(String[] args) {
     // 创建两个线程
     Thread minPriority = new Thread(new MinPriority(), "优先级较低的线程");
     Thread maxPriority = new Thread(new MaxPriority(), "优先级较高的线程");
     minPriority.setPriority(Thread.MIN_PRIORITY);

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

qiaodan81 发表于 2023-7-5 23:10
现在线程使用 以及线程等待基本都用框架了,
shksky 发表于 2023-7-5 23:36
wzw001 发表于 2023-7-6 00:14
eagle1996 发表于 2023-7-6 00:39
qiaodan81 发表于 2023-7-5 23:10
现在线程使用 以及线程等待基本都用框架了,

框架是啥意思m
afo2023 发表于 2023-7-6 03:20
有问题的,以后还望大佬多指教
 楼主| jayqia 发表于 2023-7-6 07:45
qiaodan81 发表于 2023-7-5 23:10
现在线程使用 以及线程等待基本都用框架了,

哈哈,这个是学校课程里面的内容,确实现在的开发都是在框架基础上进行修补
bean0283 发表于 2023-7-6 09:09

常用的是spring,spring mvc,spring boot,提高开发效率
ruanjl 发表于 2023-7-6 09:32
谢谢分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 22:37

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表