Java中的进程和线程

进程定义

进程是正在运行的程序,是系统进行资源分配和调用的独立单位,每一个进程都有它自己的内存空间和系统资源

线程的定义

线程是进程中单个顺序控制流,是一种执行路径

单线程: 一个进程如果只有一条路径则被称为单线程

多线程: 一个进程如果有多条执行路径,则被称为多线程

多线程的实现之继承Thread类

方式1:继承Thread类(要重写run方法)

package day4;
​
public class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(i);
        }
    }
}
​
package day4;
​
public class ThreadTest{
    public static void main(String[] args) {
        MyThread myThread1 = new MyThread();
        MyThread myThread2 = new MyThread();
        myThread1.start();
        myThread2.start();
​
    }
}
​

为什么要重写run方法

因为run方法是用来封装被线程执行的代码

run方法和start方法的区别

run():封装线程的执行的代码,直接调用,相当于普通方法

start():启动线程 然后JVM调用此线程的run方法

设置和获取线程名称

package day4;
​
public class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName()+":   "+i);
        }
    }
     public MyThread(){
​
     }
     public MyThread(String name){
        super(name);
     }
}
​

package day4;
​
public class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName()+":   "+i);
        }
    }
     public MyThread(){
​
     }
     public MyThread(String name){
        super(name);
     }
}
​

通过在MyThread类中创建有参构造方法,传递名称(只能手动创建不能使用快捷方法创建)

package day4;
​
public class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName()+":   "+i);
        }
    }
}
​

package day4;
​
public class ThreadTest{
    public static void main(String[] args) {
        MyThread myThread1 = new MyThread();
        MyThread myThread2 = new MyThread();
        myThread1.setName("小明报数");
        myThread2.setName("小红报数");
        myThread1.start();
        myThread2.start();
    }
}
​

通过setName方法设置线程名称

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

package day4;
​
public class ThreadTest{
    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName());
    }
}
​

线程的优先级

package day4;
​
public class ThreadTest{
    public static void main(String[] args) {
        MyThread myThread1 = new MyThread();
        MyThread myThread2 = new MyThread();
        MyThread myThread3 = new MyThread();
        myThread1.setName("小明");
        myThread2.setName("小红");
        myThread3.setName("小刚");
        System.out.println(Thread.MAX_PRIORITY);
        System.out.println(Thread.MIN_PRIORITY);
        System.out.println(Thread.NORM_PRIORITY);
        System.out.println("=================");
        myThread1.setPriority(1);
        myThread2.setPriority(3);
        myThread3.setPriority(10);
        myThread1.start();
        myThread2.start();
        myThread3.start();
    }
}
​

Thread.MAX_PRIORITY是最高的线程为10

Thread.MIN_PRIORITY是最低的线程为1

Thread.NORM_PRIORITY是默认线程为5

线程的优先级表示的是线程抢占的概率 线程优先级越大 概率越大

线程控制

  1. static void sleep(long millis)使当前正在执行的线程停留(暂停执行)指定的毫秒数

  2. void join()等待这个线程死亡 只有这个线程死亡之后其他线程才能执行

  3. void setDaemon(boolean on)将此线程标记为守护线程,当运行线程都为守护线程的时候Java虚拟机将退出

package day4;
​
public class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName()+":   "+i);
            try {
                sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
​

package day4;
​
public class ThreadTest{
    public static void main(String[] args) {
        MyThread myThread1 = new MyThread();
        MyThread myThread2 = new MyThread();
        MyThread myThread3 = new MyThread();
        myThread1.setName("小明");
        myThread2.setName("小红");
        myThread3.setName("小刚");
        myThread1.start();
        myThread2.start();
        myThread3.start();
    }
}
​

package day4;
​
public class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName()+":   "+i);
        }
    }
}
​
package day4;
​
public class ThreadTest{
    public static void main(String[] args) throws InterruptedException {
        MyThread myThread1 = new MyThread();
        MyThread myThread2 = new MyThread();
        MyThread myThread3 = new MyThread();
        myThread1.setName("小明");
        myThread2.setName("小红");
        myThread3.setName("小刚");
        myThread1.start();
        myThread1.join();
        myThread2.start();
        myThread3.start();
    }
}
​

只有在第一个执行完毕后 后两个才开始执行

package day4;
​
public class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName()+":   "+i);
        }
    }
}
​

package day4;
​
public class ThreadTest{
    public static void main(String[] args) throws InterruptedException {
        MyThread myThread1 = new MyThread();
        MyThread myThread2 = new MyThread();
        MyThread myThread3 = new MyThread();
        myThread1.setName("小明");
        myThread2.setName("小红");
        //将myThread1、myThread2设置为守护线程 当主线程结束后守护线程就结束
        myThread1.setDaemon(true);
        myThread2.setDaemon(true);
        myThread1.start();
        myThread2.start();
        Thread.currentThread().setName("主线程");
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+"   "+i);
        }
    }
}
​

当主线程结束以后 守护线程不会立即结束 还会挣扎一会

线程的生命周期

阻塞是不能立马进入运行状态的 只有就绪状态可以立马进入运行状态*

多线程的实现之实现Runnable接口的方式

方式2:实现Runnable接口

定义一个类实现Runnable接口 创建Thread类 把实现Runnable接口的类对象作为构造方法的参数

package day5;
​
public class MyRunnable implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName()+"  "+i);
        }
    }
}
​

package day5;
​
public class RunnableApplication {
    public static void main(String[] args) {
        MyRunnable mr = new MyRunnable();
        Thread thread1 = new Thread(mr,"高铁");
        Thread thread2 = new Thread(mr,"飞机");
        thread1.start();
        thread2.start();
    }
}
​

注意: 不能直接在 MyRunnable类中使用getName方法获取线程的名称 要通过Thread.currentThread().getName()方法获取

实现Runnable类相对于Thread的好处

  1. 避免Java单继承的局限性

  2. 适合多个相同程序代码去处理同一个资源的情况,把线程和程序的代码、数据有效分离

线程案例之卖票

案例:共有100张票 ,三个窗口要卖它

package day6;
​
public class ticketRunnable implements Runnable{
    int ticket=100;
    @Override
    public void run() {
        while (true){
            if (ticket>0){
                System.out.println(Thread.currentThread().getName()+"刚刚卖的是第几张票:"+ticket);
                ticket--;
            }
        }
    }
}
​
package day6;
​
public class ticketApplication {
    public static void main(String[] args) {
        ticketRunnable tr = new ticketRunnable();
        Thread thread1 = new Thread(tr,"窗口1");
        Thread thread2 = new Thread(tr,"窗口2");
        Thread thread3 = new Thread(tr,"窗口3");
        thread1.start();
        thread2.start();
        thread3.start();
    }
}
​

我们发现这个和我们想的不一样

因为刚刚那段代码存在同步代码块的安全问题

同步安全问题的的标准

  1. 多线程

  2. 数据共享

  3. 多条语句操作共享数据

怎样解决呢?

我们可以在同步代码块加一个锁

package day6;
​
public class ticketRunnable implements Runnable{
   private int ticket=100;
    private  Object o=new Object();
    @Override
    public void run() {
        while (true){
            synchronized (o) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (ticket>0){
                    System.out.println(Thread.currentThread().getName()+"刚刚卖的是第几张票:"+ticket);
                    ticket--;
                }
            }
        }
    }
}
​

package day6;
​
public class ticketApplication {
    public static void main(String[] args) {
        ticketRunnable tr = new ticketRunnable();
        Thread thread1 = new Thread(tr,"窗口1");
        Thread thread2 = new Thread(tr,"窗口2");
        Thread thread3 = new Thread(tr,"窗口3");
        thread1.start();
        thread2.start();
        thread3.start();
    }
}
​

此时不存在刚刚的问题

注意: 同步代码块的锁必须是一样的不可以在synchronized里面new一个要在整个类里面定义

注意: 同步代码块的锁必须是一样的不可以在synchronized里面new一个要在整个类里面定义

注意: 同步代码块的锁必须是一样的不可以在synchronized里面new一个要在整个类里面定义

synchronized的好处:解决了线程安全问题

坏处:当线程很多时 每一个线程去判断同步上的锁,很消耗资源,降低效率

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python学习笔记----面向对象(十)

一、什么是类 类是一个抽象的模板&#xff0c;用于创建具体的实例。可以将类理解为一个蓝图&#xff0c;它定义了一系列对象共有的属性&#xff08;数据&#xff09;和方法&#xff08;函数&#xff09;。类是对一组具有相同属性和功能的对象的抽象。例如&#xff0c;你可以定…

数据结构——循环结构:for循环

今天是星期五&#xff0c;明天休息&#xff0c;后天补课&#xff0c;然后就是运动会&#xff0c;接着是放假。&#xff08;但这些都和我没关系啊&#xff0c;哭死&#xff01;&#xff09;今天脑袋难得清醒一会儿&#xff0c;主要是醒的比较早吧&#xff0c;早起学了一会&#…

【VueUse】超越基本功能的高级 Vue 元素操作

在vue开发中我们经常需要操作DOM元素&#xff0c;从简单的添加类到动态创建元素&#xff0c;这些操作都是不可避免的。而在VueUse库中&#xff0c;Elements相关API函数为我们提供了一系列强大而灵活的工具&#xff0c;帮助我们更轻松地处理DOM元素。无论是优雅地处理元素、动态…

[XYCTF新生赛]-PWN:fmt解析(scanf格式化字符串漏洞,任意地址写)

查看保护 查看ida 这里没什么好说的 完整exp&#xff1a; from pwn import* context(log_leveldebug) #pprocess(./fmt) premote(gz.imxbt.cn,20975) backdoor0x4012BEp.recvuntil(bgift: ) printf_addrint(p.recv(14),16) print(hex(printf_addr)) libcELF(./libc-2.31.so) …

HTML5实用大全(Part.2)

引言&#xff1a; 哈喽&#xff0c;各位小伙伴们大家好呀&#xff0c;学习了上一篇关于HTML5的文章后&#xff0c;你是否对于入门HTML5有了一定的基础了呢&#xff0c;本篇博客我们将继续学习HTML5的不同标签&#xff0c;跟上队伍&#xff0c;准备出发咯&#xff01; 1.标签之…

js APIS part2

什么是事件&#xff1f; 事件是在编程时系统内发生的 动作 或者发生的事情。比如用户在网页上 单击 一个按钮 什么是事件监听&#xff1f; 就是让程序检测是否有事件产生&#xff0c;一旦有事件触发&#xff0c;就立即调用一个函数做出响应&#xff0c;也称为 绑定事件或者注册…

2024年钉钉群直播回放如何永久保存

工具我已经打包好了&#xff0c;有需要的自己取一下 链接&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;1234 --来自百度网盘超级会员V10的分享 1.首先解压好我给大家准备好的压缩包 2.再把逍遥一仙下载器压缩包也解压一下 3.打开逍遥一仙下载器文件夹里面的M3U8…

python实验一 简单的递归应用

实验一 实验题目 1、兔子繁殖问题(Fibonacci’s Rabbits)。一对兔子从出生后第三个月开始&#xff0c;每月生一对小兔子。小兔子到第三个月又开始生下一代小兔子。假若兔子只生不死&#xff0c;一月份抱来一对刚出生的小兔子&#xff0c;问一年中每个月各有多少只兔子。 &…

软件工程全过程性文档(软件全套文档整理)

软件项目相关全套精华资料包获取方式①&#xff1a;进主页。 获取方式②&#xff1a;本文末个人名片直接获取。 在软件开发的全过程中&#xff0c;文档是记录项目进展、决策、设计和测试结果的重要工具。以下是一个简要的软件全过程性文档梳理清单&#xff1a; 需求分析阶段…

基于 AI 的数据库助手-Chat2DB

序言 现在已经开始步入 AI 时代&#xff0c;AI 产品也已经络绎不绝。今天&#xff0c;给大家介绍一款数据库的 AI 产品 —— Chat2DB。 一、什么是 Chat2DB Chat2DB 由阿里提供的一个数据库管理、数据开发、数据分析的工具&#xff0c;它是一个 AI 原生的数据库管理工具&…

Spring 当中的Bean 作用域

Spring 当中的Bean 作用域 文章目录 Spring 当中的Bean 作用域每博一文案1. Spring6 当中的 Bean的作用域1.2 singleton 默认1.3 prototype1.4 Spring 中的 bean 标签当中scope 属性其他的值说明1.5 自定义作用域&#xff0c;一个线程一个 Bean 2. 总结:3. 最后&#xff1a; 每…

JavaScript基础(三)

JS的数据类型 数据类型&#xff0b;解释 undefined 如var num;变量num没有初始值将被赋予undefined[基本数据类型]。 null 表示一个空值&#xff0c;与undefined值相等[对象]。 number 例:var num10; //整数&#xff0c;var num10.5; //浮点型。 boolean 布尔型&…

【linuxC语言】fcntl和ioctl函数

文章目录 前言一、功能介绍二、具体使用2.1 fcntl函数2.2 ioctl函数 三、拓展&#xff1a;填写arg总结 前言 在Linux系统编程中&#xff0c;经常会涉及到对文件描述符、套接字以及设备的控制操作。fcntl和ioctl函数就是用来进行这些控制操作的两个重要的系统调用。它们提供了对…

专业渗透测试 Phpsploit-Framework(PSF)框架软件小白入门教程(一)

本系列课程&#xff0c;将重点讲解Phpsploit-Framework框架软件的基础使用&#xff01; 本文章仅提供学习&#xff0c;切勿将其用于不法手段&#xff01; Phpsploit-Framework&#xff08;简称 PSF&#xff09;框架软件&#xff0c;是一款什么样的软件呢&#xff1f; Phpspl…

[数据结构]———归并排序

具体代码&#xff1a;在gitee仓库&#xff1a;登录 - Gitee.com 目录 ​编辑 1.基本思想&#xff1a; 2. 代码解析 1.分析 2.逻辑图 3.运行结果 1.基本思想&#xff1a; 归并排序&#xff08;MERGE-SORT&#xff09;是建立在归并操作上的一种有效的排序算法,该算法是采用分…

Redis__三大日志

文章目录 &#x1f60a; 作者&#xff1a;Lion J &#x1f496; 主页&#xff1a; https://blog.csdn.net/weixin_69252724 &#x1f389; 主题&#xff1a;Redis__三大日志 ⏱️ 创作时间&#xff1a;2024年04月30日 ———————————————— 对于MySQL来说, 有…

C# WinForm —— 08 Form初始化、布局、注册事件

Form 初始化 Form初始化的时候会调用 Designer.cs 里的 InitializeComponent(); 函数&#xff0c;在InitializeComponent(); 函数里面有Load Form语句时会调用 FrmLogin_Load()函数 Form布局 两种方式&#xff1a; 拖控件到窗体&#xff0c;设置属性在Load事件中写代码添加…

Python梯度提升决策树库之lightgbm使用详解

概要 LightGBM是一个快速、分布式、高性能的梯度提升决策树(Gradient Boosting Decision Tree)库,它在机器学习和数据挖掘领域被广泛应用。本文将介绍LightGBM库的安装方法、主要特性、基本功能、高级功能、以及在实际应用中的场景和总结。 安装 首先,需要安装LightGBM库…

一文读懂:到底什么是SCDN?

最近大家一定经常听到CDN这个词&#xff0c;对于之前没接触过这个行业的人&#xff0c;可能会听的云里雾里&#xff0c;不明所以。 那到底什么是SCDN呢&#xff1f; 简单理解&#xff1a;SCDN数据快递前置仓&#xff1f; SCDN&#xff0c;全称 Secure Content Delivery Networ…