Java多线程学习(Day02)

这篇具有很好参考价值的文章主要介绍了Java多线程学习(Day02)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

  • 线程简介

  • 线程实现(重点)

  • 线程状态

  • 线程同步(重点)

  • 线程通信问题

线程实现:

方式一:继承Thread类

/**
 * TODO
 * @author 清莲孤舟
 * @CreateDate 2023/9/17/9:28
 * 创建线程的方式一:通过继承Thread类实现
 */
//继承Thread类
public class demo01 extends Thread {
//重写run方法
    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("副线程"+i);
        }
    }
//main主线程
    public static void main(String[] args) {
        demo01 demo01 = new demo01();
        //start方法启用线程
        demo01.start();
        //run()方法启用线程
        demo01.run();
        for (int i = 0; i < 20; i++) {
            System.out.println("主线程"+i);
        }
    }
}

  我们先调用run方法运行(注意run()方法在主函数中的顺序):

副线程0    副线程1    副线程2    副线程3    副线程4    副线程5    副线程6    副线程7    副线程8    副线程9    
副线程10    副线程11    副线程12    副线程13    副线程14    副线程15    副线程16    副线程17    副线程18    副线程19

主线程0    主线程1    主线程2    主线程3    主线程4    主线程5    主线程6    主线程7    主线程8    主线程9    
主线程10    主线程11    主线程12    主线程13    主线程14    主线程15    主线程16    主线程17    主线程18    主线程19    

  可以看出程序先运行完run线程再运行main主线程。符合程序按序执行的规制。同理如果将run()方法放在主函数的最后,那么先输出的将是"主线程"随后是"副线程"。

  接下来我们调用start()方法:

主线程0    副线程0    主线程1    主线程2    主线程3    主线程4    副线程1    主线程5    主线程6    主线程7    副线程2    主线程8    主线程9    主线程10   主线程11   主线程12   副线程3    
主线程13 主线程14 主线程15 主线程16 主线程17 主线程18 主线程19 副线程4 副线程5 副线程6 副线程7 副线程8 副线程9 副线程10 副线程11 副线程12 副线程13
副线程14 副线程15 副线程16 副线程17 副线程18 副线程19

  显而易见程序并不是按序执行的,而是交替并行的。这便是上节中介绍的并发,在一段时间内交替完成。

  (PS:如果你在运行时发现输出结果并不是交替的,那么请将for循环次数增加,20次循环对于你的电脑来说太简单了)

Java多线程学习(Day02)

方式二:实现Runnable接口(重点)

/**
 * TODO
 * @author Cooper
 * @CreateDate 2023/9/17/10:26
 * 创建线程方式二:实现Runnable接口
 */
public class demo02 implements Runnable{
//   同样的重写run()方法
    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.print("副线程"+i+"\t");
        }
    }
    public static void main(String[] args) {
        demo02 demo02 = new demo02();
//        创建线程对象,通过线程对象开启线程
        Thread thread = new Thread(demo02);
        thread.start();
//      可以简写为该写法new Thread(demo02).start();
        for (int i = 0; i < 20; i++) {
            System.out.print("主线程"+i+"\t");
        }
    }
}

  源码解析:

//Runnable源码 只有一个run()方法
public interface Runnable {
    public abstract void run();
}
//Thread方法 需要传入一个实现Runnable的对象
public Thread(Runnable target) {
    init(null, target, "Thread-" + nextThreadNum(), 0);
}

  运行结果:

主线程0    副线程0    主线程1    副线程1    主线程2    主线程3    主线程4    主线程5    副线程2    主线程6    
主线程7    主线程8    副线程3    主线程9    副线程4    主线程10    主线程11    主线程12    主线程13    主线程14    
主线程15    主线程16    主线程17    副线程5    主线程18    副线程6    副线程7    主线程19    副线程8    副线程9    
副线程10    副线程11    副线程12    副线程13    副线程14    副线程15    副线程16    副线程17    副线程18    副线程19    

线程并发案例:

  这里使用狂神的案例:

 1 /**
 2  * TODO
 3  *
 4  * @author Cooper
 5  * @CreateDate 2023/9/17/10:42
 6  */
 7 public class demo03 implements Runnable{
 8     private int TicketNumber = 10;
 9     @Override
10     public void run() {
11         while (true){
12             if(TicketNumber==0){
13                 break;
14             }
15             try {
16                 //线程暂停200ms
17                 Thread.sleep(200);
18             } catch (InterruptedException e) {
19                 e.printStackTrace();
20             }
21             //Thread.currentThread().getName()获取当前线程的名字
22             System.out.println(Thread.currentThread().getName()+"===>拿到了第"+TicketNumber--+"票");
23         }
24     }
25     public static void main(String[] args) {
26         demo03 ticket = new demo03();
27         new Thread(ticket,"小张").start();
28         new Thread(ticket,"小李").start();
29         new Thread(ticket,"小王").start();
30     }
31 }

  运行结果:

小李===>拿到了第8票
小张===>拿到了第10票
小王===>拿到了第9票
小王===>拿到了第6票
小李===>拿到了第7票
小张===>拿到了第7票
小李===>拿到了第3票
小王===>拿到了第4票
小张===>拿到了第5票
小李===>拿到了第2票
小王===>拿到了第2票
小张===>拿到了第2票
小张===>拿到了第1票
小王===>拿到了第1票
小李===>拿到了第1票

  此时我们发现了一些问题--->同一张票被两个人拿到了! 这就是线程不安全,数据紊乱。后序我们将通过线程同步解决这个问题。

方式三:实现callable接口(了解即可)

 1 import java.util.ArrayList;
 2 import java.util.List;
 3 import java.util.concurrent.*;
 4 /**
 5  * TODO
 6  *
 7  * @author Cooper
 8  * @CreateDate 2023/9/17/14:52
 9  */
10 public class demo04 implements Callable<List<String>> {
11     @Override
12     public List<String> call() throws Exception {
13         List<String> result = new ArrayList<>();
14         for (int i = 0; i < 5; i++) {
15             result.add(Thread.currentThread().getName()+"===>"+i);
16             System.out.print(Thread.currentThread().getName()+"===>"+i+"\t");
17         }
18         return result;
19     }
20     public static void main(String[] args) throws ExecutionException, InterruptedException {
21         demo04 test1 = new demo04();
22         demo04 test2 = new demo04();
23         demo04 test3 = new demo04();
24 //        创建服务开启三个线程
25         ExecutorService service = Executors.newFixedThreadPool(3);
26         System.out.println("运行中:");
27 //        提交执行
28         Future<List<String>> r1 = service.submit(test1);
29         Future<List<String>> r2 = service.submit(test2);
30         Future<List<String>> r3 = service.submit(test3);
31 //        获取结果
32         List<String> result1 = r1.get();
33         List<String> result2 = r2.get();
34         List<String> result3 = r3.get();
35         System.out.println();
36 
37         System.out.println("运行结束:");
38         System.out.println(result1);
39         System.out.println(result2);
40         System.out.println(result3);
41 //        关闭服务
42         service.shutdown();
43     }
44 }

  运行结果:

运行中:
pool-1-thread-2===>0    pool-1-thread-1===>0    pool-1-thread-2===>1    pool-1-thread-3===>0    
pool-1-thread-2===>2    pool-1-thread-1===>1    pool-1-thread-2===>3    pool-1-thread-1===>2    
pool-1-thread-3===>1    pool-1-thread-1===>3    pool-1-thread-2===>4    pool-1-thread-1===>4    
pool-1-thread-3===>2    pool-1-thread-3===>3    pool-1-thread-3===>4    
运行结束:
[pool-1-thread-1===>0, pool-1-thread-1===>1, pool-1-thread-1===>2, pool-1-thread-1===>3, pool-1-thread-1===>4]
[pool-1-thread-2===>0, pool-1-thread-2===>1, pool-1-thread-2===>2, pool-1-thread-2===>3, pool-1-thread-2===>4]
[pool-1-thread-3===>0, pool-1-thread-3===>1, pool-1-thread-3===>2, pool-1-thread-3===>3, pool-1-thread-3===>4]

 文章来源地址https://www.toymoban.com/news/detail-712265.html

到了这里,关于Java多线程学习(Day02)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 学习RHCSA的day.02

    目录 2.3常用简单命令 2.4使用Bash执行命令 2.5 命令帮助 常用系统工作命令 1、echo命令 echo命令用于在终端设备上输出字符串或变量提取后的值,语法格式为:“echo [字符串] [$变量]”。 这是在Linux系统中最常用的几个命令之一,但操作却非常简单,执行“echo 字符串”或“ech

    2024年02月02日
    浏览(30)
  • 【学习笔记】自学Unity Day02

    前言:主要想记录下自己自学的过程、期间遇见的问题、不同版本需要调整的地方,方便以后复习能及时找到对应的部分;同时也希望给想要入门游戏开发、学习unity的各位一些经验,减少一些弯路 学习资料目前主要依靠 unity 官网,我的想法是先根据官方的游戏套件能够做出

    2024年04月17日
    浏览(23)
  • LiangGaRy_学习笔记_Day02

    1、安装 openeuler 1.1、镜像准备 openeuler是一个系统;以下是基于百度百科的解释: HUAWEI 发布的操作系统: openEuler 是开放原子开源基金会(OpenAtom Foundation)孵化及运营的开源项目。 欧拉操作系统(openEuler, 简称“欧拉”)是面向数字基础设施的操作系统, 支持服务器、云计算

    2023年04月24日
    浏览(40)
  • JavaSE学习进阶day07_02 异常

    异常,就是不正常的意思。在生活中:医生说,你的身体某个部位有异常,该部位和正常相比有点不同,该部位的功能将受影响.在程序中的意思就是: 异常 : 指的是程序在执行过程中,出现的非正常的情况,最终会导致 JVM 的非正常停止 。 在Java等面向对象的编程语言中, 异常

    2023年04月24日
    浏览(39)
  • 自定义线程池 02 - 初步实现线程池

    完整代码已上传gitee ,地址 :朱元杰的开源仓库 – ThreadPool核心源码仿写 完整文章栏目地址在:Fearless____的博客 - ThreadPool仿写 上一步我们已经实现阻塞队列(任务队列),接下来 初步实现 线程池 将线程池类定义为 MyThreadPool 线程池中需要有如下属性: 任务队列 private My

    2024年02月13日
    浏览(29)
  • JavaSE学习进阶day03_02 内部类

    2.1.1 什么是内部类 将一个类A定义在另一个类B里面,里面的那个类A就称为 内部类 ,B则称为 外部类 。可以把内部类理解成寄生,外部类理解成宿主。 2.1.2 什么时候使用内部类 一个事物内部还有一个独立的事物,内部的事物脱离外部的事物无法独立使用 人里面有一颗心脏。

    2023年04月15日
    浏览(33)
  • 前端TypeScript学习day02-TS常用类型

    (创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹) 目录 TypeScript 常用类型 接口  元组  类型推论 类型断言 字面量类型 枚举 any 类型 typeof  当一个对象类型被多次使用时,一般会使用接口(interface)来描述对象的类型,达到

    2024年02月08日
    浏览(50)
  • 计算机网络学习day02|HTTP协议

    目录 一、HTTP报文格式长什么样?是如何分割的? 请求行 状态行 头部字段 常用头字段 小结 二、HTTP提供了哪些方法?GET和POST的区别是什么? 1.HTTP有哪些方法 2.GET/HEAD 3.PSOT/PUT 小结 三、URI和URL URI 的格式 URI 的基本组成 URI 的查询参数 小结 四、HTTP有哪些状态码?分别代表什

    2024年04月23日
    浏览(46)
  • 【STM32】STM32学习笔记-STM32简介(02)

    STM32是ST公司基于ARM Cortex-M内核开发的32位微控制器 STM32常应用在嵌入式领域,如智能车、无人机、机器人、无线通信、物联网、工业控制、娱乐电子产品等 STM32功能强大、性能优异、片上资源丰富、功耗低,是一款经典的嵌入式微控制器 1.1 STM32是什么 STM32是一系列由ST Micro

    2024年02月04日
    浏览(37)
  • 蓝桥杯备赛day02 -- 算法训练题 拿金币Java

    目录 题目: 问题描述 输入格式 输出格式 解题过程 第一步 定义dp数组 第二步 确定 dp 数组递推公式  第三步 dp数组的初始化 第四步 dp数组的遍历顺序 第五步 举例说明  报错:内存超限 用dp数组去存储位置上的金币 dp数组从二维降为一维  收获:   有一个N x N的方格,每一个

    2024年01月17日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包