Java,多线程,线程的两种创建方式

news2024/12/23 3:50:53

首先是多线程的一些相关概念:

相关概念:

程序(program):为完成特定任务,用某种语言编写的一组指令的集合。即指一段静态(指不在执行中)的代码。

进程(process):程序的一次执行过程,或是正在内存中运行的应用程序。

        ·每个进程都有一个独立的内存空间,系统运行一个程序即是一个进程从创建、运行到消亡的过程。(声明周期)

        ·程序是静态的,进程是动态的。

        ·进程作为操作系统调度和分配资源的最小单位(亦是系统运行程序的基本单位),系统在运行时会为每个进程分配不同的内存区域。

线程(thread):进程可以进一步细化为线程,时程序内部的一条执行路径。一个进程中至少有一个线程。

        ·一个进程同一时间若并行执行多个线程,就是多线程的。

        ·线程是作为CPU调度和执行的最小单位。

        ·一个进程中的多个线程共享相同的内存单元,它们从一个堆中分配对象,可以访问相同的变量和对象。这就使得线程间通信更简便、高效。但多个线程操作共享的系统资源就可能会带来安全的隐患。

        注:不同的进程之间是不共享内存的。进程之间的数据交换和通信的成本很高。

线程调度:

        ·分时调度:所有线程轮流使用CPU的使用权,并且平均分配每个线程占用CPU的时间。

        ·抢占式调度:让优先级高的线程以较大的概率优先使用CPU。如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度。

多线程程序的优点:

        提高应用程序的响应。对图形化界面更有意义,可增强用户体验。

        提高计算机系统CPU的利用率。

        改善程序结构。将既长又复杂的进程分为多个线程,独立运行,利于理解和修改。

并行与并发:

并行(parallel):指两个或多个事件在同一时刻发生。指在同一时刻,有多条指令在多个CPU上同时执行。

并发(concurrency):指两个或多个事件在同一个时间段内发生。即在同一段时间内,有多条指令在单个CPU上快速轮换、交替执行,使得在宏观上具有多个进程同时执行的效果。

Java,多线程,线程创建方式一:继承Thread类

 Java语言的JVM允许程序运行多个线程,使用java.lang.Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例。

Thread类的特性:

    ①每个线程都是通过某个特定的Thread对象的run( )方法来完成操作的,因此把run( )方法称为线程执行体。

    ②通过该Thread对象的start( )方法来启动这个线程,而非直接调用run( )方法。

    ③想要实现多线程,必须在主线程中创建新的线程对象。

通过继承Thread类来创建并启动多线程的步骤如下:

①定义Thread的子类,并重写该类的run( )方法,该run( )方法的方法体就代表了线程需要完成的任务。

②创建Thread类的子类的实例,即创建了线程对象。

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

start( )的作用:①启动线程②调用当前线程的run( )方法。

以下代码的实现为例:

两个线程分别遍历10000以内的偶数:

public class EvenNumberTest

{

    public static void main(String[] args)

    {

        //③创建当前Thread类的子类的对象
        PrintNumber t1 = new PrintNumber();
        //通过对象调用start()方法
        t1.start();

        //main方法所在的线程的执行的操作
        for (int i = 1; i <= 10000; i++)
        {
            if(i % 2 == 0)
            {
                System.out.println(i + "及你太美");
            }
        }
    }
}

//①创建一个继承于Thread的子类
class PrintNumber extends Thread
{
    //②重写Thread类的run方法,并将此线程的要执行的操作,声明在此方法体中

    @Override
    public void run()
    {
        for (int i = 1; i <= 10000; i++)
        {
            if(i % 2 == 0)
            {
                System.out.println(i);
            }
        }
    }
}

可以发现到两个进程的交替的运行的状况:

注意点一:

如果不调用start( )方法,直接调用run( )方法,便不会开启新的线程。

注意点二:

不能让已经start的线程,再次执行start( ),否则会报异常。正确做法应该是再创建一个新的对象,用新的对象调用start( )方法。

可以利用匿名内部类的方法写出   遍历100以内的奇数和偶数的俩个线程(创建两个匿名内部类(Thread类的子类的匿名)):

class EvenNumber extends Thread
{
    @Override
    public void run()
    {
        for (int i = 1; i <= 100; i++)
        {
            if(i % 2 == 0)
            {
                System.out.println(Thread.currentThread().getName() + ": " + i);
            }
        }
    }
}

class OddNumber extends Thread
{
    @Override
    public void run()
    {
        for (int i = 1; i <= 100; i++)
        {
            if(i % 2 == 1)
            {
                System.out.println(Thread.currentThread().getName() + ": " + i);
            }
        }
    }
}

public class PrintNumberTest

{
    public static void main(String[] args
    {
//        EvenNumber e = new EvenNumber();
//        OddNumber o = new OddNumber();
//        e.start();
//        o.start();

        //方式二
        new Thread(){
            public void run()
            {
                for (int i = 1; i <= 100; i++)
                {
                    if(i % 2 == 0)
                    {
                        System.out.println(Thread.currentThread().getName() + ": " + i);
                    }
                }
            }
        }.start();

        new Thread(){
            public void run()
            {
                for (int i = 1; i <= 100; i++)
                {
                    if(i % 2 == 1)
                    {
                        System.out.println(Thread.currentThread().getName() + ": " + i);
                    }
                }
            }
        }.start();
    }
}

Java,多线程,线程创建方式二:实现Runnable接口

步骤:

①创建一个实现Runnable接口的类

②实现接口中的run( )方法,将此线程要执行的操作,声明在此方法体中。

③创建当前实现类的对象

④将此对象作为参数传递到Thread类的构造器中,创建Thread类的实例。

⑤Thread类的实例调用start( )方法。

基本步骤的样例如下:

//①创建一个实现Runnable接口的类
class EvenNumberPrint implements Runnable
{
//②创建接口中的run()方法,将此线程要执行的操作,声明在此方法体中
    @Override
    public void run()
    {
        for (int i = 1; i <= 100; i++)
        {
            if(i % 2 == 0)
            {
                System.out.println(Thread.currentThread().getName() + ": " + i);
            }
        }
    }
}
public class EvenNumberTest
{
    public static void main(String[] args)
    {
        EvenNumberPrint e = new EvenNumberPrint();//创建Runnable类的实现类的对象。
        Thread thread = new Thread(e);//创建thread类的对象,调用参数为Runnable的实现类的构造器,将实现类的对象代入构造器中去。
        thread.start();//直接调用Thread的对象的start方法。
        for (int i = 1; i <= 100; i++)
        {
            if(i % 2 == 1)
            {
                System.out.println(Thread.currentThread().getName() + ": " + i);
            }
        }


        Thread tt = new Thread(e);//要再创建一条新的线程,执行同样的操作,不用再创建实现类的对象,只要再创建Thread的对象就可以,参数用的依然是同一个实现类的对象。
        tt.start();
    }
}
同样 可以利用匿名内部类的方法写出   遍历100以内的奇数和偶数的俩个线程:
public class PrintNumberTest
{
    public static void main(String[] args)
    {
//        EvenNumber ee = new EvenNumber();
//        OddNumber oo = new OddNumber();
//        Thread t1 = new Thread(ee);
//        Thread t2 = new Thread(oo);
//        t1.start();
//        t2.start();


        //匿名的Thread的子类,参数为匿名的Runnable的实现类的匿名对象。
        new Thread(new Runnable(){
            public void run()
            {
                for (int i = 1; i <= 100; i++)
                {
                    if(i % 2 == 0)
                    {
                        System.out.println(Thread.currentThread().getName() + ": " + i);
                    }
                }
            }
        }).start();
        new Thread(new Runnable(){
            public void run()
            {
                for (int i = 1; i <= 100; i++)
                {
                    if(i % 2 == 1)
                    {
                        System.out.println(Thread.currentThread().getName() + ": " + i);
                    }
                }
            }
        }).start();
    }
}


class EvenNumber implements Runnable
{
    public void run()
    {
        for (int i = 1; i <= 100; i++)
        {
            if(i % 2 == 0)
            {
                System.out.println(Thread.currentThread().getName() + ": " + i);
            }
        }
    }
}


class OddNumber implements Runnable
{


    @Override
    public void run()
    {
        for (int i = 1; i <= 100; i++)
        {
            if(i % 2 == 1)
            {
                System.out.println(Thread.currentThread().getName() + ": " + i);
            }
        }
    }
}
线程创建的俩种方式的对比:
共同点:
①启动线程,使用的都是Thread类中定义的start( )方法。
②创建的线程对象,都是Thread类或Thread的子类的实例。
不同点:
方式一是类的继承,方式二是接口的实现。
建议使用Runnable接口的方式
实现Runnable接口的方式的好处:
①一个类可以实现多个接口,避免了类的单继承的局限性。
②创建多个线程对象的构造器的参数(Runnable的实现类)可以使用同一个实现类的对象,更适合处理有共享数据的问题。
③实现了代码和数据的分离。
联系:
Thread类实现了Runnable接口。体现了代理模式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1194413.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

十分钟了解回归测试

1. 什么是回归测试&#xff08;Regression Testing&#xff09; 回归测试是一个系统的质量控制过程&#xff0c;用于验证最近对软件的更改或更新是否无意中引入了新错误或对以前的功能方面产生了负面影响&#xff08;比如你在家中安装了新的空调系统&#xff0c;发现虽然新的空…

34 mysql limit 的实现

前言 这里来看一下 我们常见的 mysql 分页的 limit 的相的处理 这个问题的主要是来自于 之前有一个需要处理 大数据量的数据表的信息, 将数据转移到 es 中 然后就是用了最简单的 “select * from tz_test limit $pageOffset, $pageSize ” 来分页处理 但是由于 数据表的数…

[autojs]逍遥模拟器和vscode对接

第一步&#xff1a;启动autojs服务 第二步&#xff1a;去cmd查看ip地址&#xff0c;输入ipconfig 第三步&#xff1a;打开逍遥模拟器中的sutojs-左上角- 连接电脑&#xff0c;然后输入WLAN或者其他ip也行&#xff0c;根据自己电脑实际情况确认 此时vscode显示连接成功。我们写…

上传ipa到appstore最简单的方法

假如使用原生xcode开发ios的app&#xff0c;可以使用xcode提交打包好的ipa文件到app store&#xff0c;但是假如使用hbuilderx或者apicloud等H5工具开发的app&#xff0c;假如没有mac电脑&#xff0c;是无法将ipa提交到app store的。 因为苹果开发者并不能在线上传ipa到app st…

数据结构-图的应用

最小生成树&#xff08;最小代价树&#xff09; 对于一个带权连通无向图G(V,E)&#xff0c;生成树不同&#xff0c;每棵树的权&#xff08;即树中所有边上的权值之和)也可能不同。设R为G的所有生成树的集合&#xff0c;若T为R中边的权值之和最小的生成树&#xff0c;则T称为G的…

SPI简介及FPGA通用MOSI模块实现

简介 SPI&#xff08;Serial Peripheral Interface&#xff0c;串行外围设备接口&#xff09;通讯协议&#xff0c;是Motorola公司提出的一种同步串行接口技术。是一种高速、全双工、同步通信总线。在芯片中只占用四根管脚用来控制及数据传输。 优缺点&#xff1a; SPI通讯协…

VM17虚拟机设置网络,本地使用工具连接虚拟机

VM17虚拟机设置网络&#xff0c;本地使用工具连接虚拟机 下载及安装虚拟机不再说明&#xff0c;网络一堆教程。此处只对VM17设置网路及本地使用工具连接虚拟机操作&#xff0c;进行说明。 我下载的是VM17&#xff0c;网上有说VM16是较稳定的版本。想尝尝鲜&#xff0c;结果耗…

linux系统源码安装php5.6手把手教程

linux系统源码安装php5.6实用教程 1、下载php5.6安装包2、开始安装3、安装成功 1、下载php5.6安装包 wget http://mirrors.sohu.com/php/php-5.6.2.tar.gz在安装之前&#xff0c;我们需要安装php5.6编译时所依赖的软件包。如下&#xff1a; yum -y install gcc gcc-c lib2、开…

docker下的nginx代理转发到tomcat

多次尝试失败原因&#xff0c;修改nginx配置文件以后&#xff0c;需要./nginx.sh -s reload 下&#xff0c;之前一直不转发&#xff0c;好像完全没有跳转的意思&#xff0c;后来查了多篇文档&#xff0c;最简单的方法如下 docker 安装 nginx 和tomcat就不多说了&#xff0c;可…

一文6个步骤带你实现接口测试入门!

一、接口测试概述 1 什么是接口测试&#xff1a; 接口测试是测试系统组件间交互的一种测试。接口测试主要用于检测外部系统与系统之间&#xff0c;内部各个子系统之间的交互点。测试的重点是要检查数据的交换&#xff0c;传递和控制管理过程&#xff0c;以及系统间的相互逻辑…

CLion配置libtorch找不到xxx.dll

项目场景&#xff1a; 使用CLion配置libtorch时遇到该问题 问题描述 使用CLion配置libtorch时&#xff0c;CMakeLists.txt文件写完后&#xff0c;cmake也能成功&#xff0c;但是一旦运行代码就会报错找不到xxx.dll&#xff0c;比如找不到torch_cuda.dll或找不到c10.dll 原因分…

jsp基本表格和简单算法表格

基本表格&#xff1b; <% page language"java" contentType"text/html; charsetUTF-8"pageEncoding"UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd…

java项目之果蔬经营平台系统(ssm框架)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的果蔬经营平台系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 管理员&#xff1a;首页、个人…

Android 12 S 系统开机流程分析-FirstStageMain(一)

开机有好几种方式启动&#xff0c;本文主要讲的是按Power键开机流程。 本文参考AOSP 12原生代码&#xff0c;链接为&#xff1a;AOSP 12 Searchhttp://aospxref.com/android-12.0.0_r3/ 目录 1. BootLoader加载 2. kernel启动 3. init进程启动 3.1 FirstStageMain 3.1.1…

Windows安装Docker(无网)

Windows安装Docker&#xff08;无网&#xff09; window无网安装Docker 1. 开启虚拟化功能 1. 开启window的虚拟化功能 方式一&#xff1a;直接在window的搜索框搜索 “启用或关闭windows功能”&#xff0c;就可以快捷进入【启用或关闭windows功能】页面 方式二&#xff1…

Gui基础使用之项目部署

&#x1f3ac; 艳艳耶✌️&#xff1a;个人主页 &#x1f525; 个人专栏 &#xff1a;《Spring与Mybatis集成整合》《Vue.js使用》 ⛺️ 越努力 &#xff0c;越幸运。 1.gui图形化界面的使用 1.1 前期准备 新建仓库&#xff0c;具体操作如下&#xff1a; 初始化readme文件&…

如何使用fiddler实现手机抓包,Filters过滤器!

一、Fiddler与其他抓包工具的区别 1、Firebug虽然可以抓包&#xff0c;但是对于分析http请求的详细信息&#xff0c;不够强大。模拟http请求的功能也不够&#xff0c;且firebug常常是需要“无刷新修改”&#xff0c;如果刷新了页面&#xff0c;所有的修改都不会保存&#xff1b…

ChatRule:基于知识图推理的大语言模型逻辑规则挖掘11.10

ChatRule&#xff1a;基于知识图推理的大语言模型逻辑规则挖掘 摘要引言相关工作初始化和问题定义方法实验 摘要 逻辑规则对于揭示关系之间的逻辑联系至关重要&#xff0c;这可以提高推理性能并在知识图谱&#xff08;KG&#xff09;上提供可解释的结果。虽然已经有许多努力&a…

Java类和对象详解

文章目录 面向对象概述类和对象类定义和使用定义使用 对象引用对象的初始化和构造构造方法默认初始化就地初始化 面向对象概述 面向对象是一种现在主流的程序设计方法&#xff0c;现如今的大部分语言都支持面向对象&#xff0c;Java的面向对象是由C的面向对象衍生而来&#xf…

AMD发布大小核 CPU,6核心直接砍成单核了

2022年 Intel 第12代酷睿发布&#xff0c;PE 大小核设计被正式带到了 PC 上。 P-Core 也就是传统的大核有着高性能、高功耗&#xff0c;而 E-Core 小核则是更讲究能效比以更低频率运行。 虽说小蝾也曾有对 Windows 调度方面的怀疑&#xff0c;但多线程性能确实实打实证明了其优…