小工具      在线工具  汉语词典  dos游戏  css  js  c++  java

Java线程

Java,java 额外说明

收录于:15天前

进程与线程

过程
在操作系统中,每个独立的执行的程序都是一个进程,计算机上都是安装的多任务操作系统,能同时执行多个应用程序。

在多任务操作系统中,逻辑上它们是同时运行的,但实际上并非如此。所有应用程序均由CPU执行。对于CPU来说,一次只能运行一个程序。操作系统给每个进程分配有限的CPU占用时间,并且占用时间在同一个时间线上。

线
每个运行的程序都是一个进程,在一个程序中还可以有多个可执行的单元,每个单元称为线程。每个进程中至少存在一个线程。

当Java程序启动时,会生成一个进程,并创建一个线程来执行main函数的代码。代码会按照调用的顺序从上到下执行,称为单线程程序。如果想让程序多端的代码交替运行,就需要创建多个线程。

线程和进程由CPU执行,逻辑上在同一时间线上同时执行。

线程创建

Java中提供了两种多线程的实现方式,一种是继承java.lang包下的Thread类,重写run()方法,在run方法类实现线程代码;另一种方法是实现java.lang.Runable接口,重写run()方法。

继承线程

//继承Thread
import java.lang.Thread;
public class App {
    
    public static void main(String[] args) {
    
        MyThread myThread=new MyThread();
        myThread.run();
        for (int i=0;i<10;i++){
    
            System.out.println("main is running");
        }
    }

    static class MyThread extends Thread{
    

        @Override
        public void run() {
    
            for(int i=0;i<10;i++){
    
                System.out.println("MyThread is running");
            }

        }
    }
}

在这里插入图片描述

上面的代码演示了单线程的情况。 run是继承Thread创建的线程。线程结束后主程序结束。

多线程需要程序连续运行才能体现出来,系统分配CPU时间。

//多线程演示用start()方法,run会抢占线程
import java.lang.Thread;
public class App {
    
    public static void main(String[] args) {
    
        MyThread myThread=new MyThread();
        myThread.start();
        while (true){
    
            System.out.println("main is running");
        }
    }

    static class MyThread extends Thread{
    

        @Override
        public void run() {
    
            while (true){
    
                System.out.println("MyThread is running");
            }

        }

    }
}

在这里插入图片描述

如图看出两个线程是交替运行,由系统膏分配CPU占用时间。注意:用start()开启线程,不能用run()会抢占线程。

多线程和单线程的区别在于CPU时间的动态利用。单线程独占,多线程系统分配。

实现Runnable接口

Thread创建线程的缺点是必须继承Thread,已经有继承关系的类不能被继承(Java单继承原则)。 Runnable接口的优点是它只实现了Thread的run方法。只需要重写逻辑,将Runnable作为参数传递给Thread即可,不需要继承Thread。

//将Runnable作为参数传到Thread
public class App {
    
    public static void main(String[] args) {
    
        Thread thread=new Thread(new MyRunnable());
        thread.start();

        Thread thread1=new Thread(new MyRunnableOne());
        thread1.start();
    }

    static class MyRunnable implements Runnable{
    

        @Override
        public void run() {
    
            while (true){
    
                System.out.println("Runnable is running");
            }

        }
    }

    static class MyRunnableOne implements Runnable{
    

        @Override
        public void run() {
    
            while (true){
    
                System.out.println("RunnableOne is running");
            }

        }
    }
}

在这里插入图片描述

线程应用

Thread和Runnable都可以实现线程,那么有什么区别呢?

线程是独立的

class MyThreadOne extends Thread{
    
    private int total=100;
    @Override
    public void run() {
    
        while (total>=1){
    
            //获取当前线程
            Thread thread=Thread.currentThread();
            //获取线程名
            String th_name=thread.getName();
            System.out.println(th_name+"正在发售第"+total--+"张票");
        }
    }
}

public class MainApp {
    

    public static void main(String[] args) {
    
        MyThreadOne myThreadOne1=new MyThreadOne();
        MyThreadOne myThreadOne2=new MyThreadOne();
        MyThreadOne myThreadOne3=new MyThreadOne();
        myThreadOne1.start();
        myThreadOne2.start();
        myThreadOne3.start();
    }

}

代码实现了继承Thread,内部有100张票,三个线程发售。
在这里插入图片描述
由结果可以发现线程Thread-0和1,2都各自发售了第100次票,显然他们是独立的。

可运行线程是协作的

package com.company.runnable;

class MyRunnable implements Runnable{
    
    private int total=100;
    @Override
    public void run() {
    
        while (total>=1){
    
            //获取当前线程
            Thread thread=Thread.currentThread();
            //获取线程名
            String th_name=thread.getName();
            System.out.println(th_name+"正在发售第"+total--+"张票");
        }
    }
}

public class MainApp {
    
    public static void main(String[] args) {
    
        Thread myThreadOne1=new Thread(new MyRunnable());
        Thread myThreadOne2=new Thread(new MyRunnable());
        Thread myThreadOne3=new Thread(new MyRunnable());
        myThreadOne1.start();
        myThreadOne2.start();
        myThreadOne3.start();

    }
}

代码继承Runnable重写run方法,内部100张票
在这里插入图片描述
由结果可以看出所有线程共享成员变量。

除了上面案例外由多态特性也可以理解,通过实例化Thread创建是不同的对象,对象间是独立的,毫无关联的。而实现Runnable接口,仅仅是重写了run()方法,他们共享成员变量。

线程生命周期及状态转换

Java对象中的任何对象都有生命周期,线程也不例外。当Thread对象被创建时,线程的生命周期就开始了。当run抛出异常或阶段关闭时,线程结束。

线程的生命周期分为五个阶段:新建状态(New)、就绪状态(Runnable)、运行状态(Running)、阻塞状态(Blocked)、死亡状态(Termminate)。线程的不同状态表明该线程当前正在运行。活动。

  1. 新建状态
    JVM分配内存,没有任何线程特征。
  2. 就绪状态
    当线程调用start()方法后,线程进入就绪状态,线程位于线程队列中,等待CPU分配。
  3. 运行状态
    获得CPU使用权后执行线程执行体,该程序处于运行状态。系统剥夺CPU使用权后,处于等待状态,等待再次占有CPU,直至程序结束。
  4. 阻塞状态
    运行的线程由于某种原因,被迫让出CPU使用权而进入阻塞状态。此时线程并没有进入等待对列,CPU由其他等待对列中的线程使用,直至解除阻塞状态,进入等待对列,等待系统分配CPU使用权后才能再次执行。
    notify()和·wait()方法可以使线程进入阻塞状态。sleep()方法使阻塞特定时间,join()加入新进程会阻塞原进程,直至新进程运行完毕。

线程调度

程序的多个线程在逻辑上是并发的。一个线程想要执行,就必须获得CPU的所有权。 Java虚拟机按照特定的机制为线程分配CPU的使用权,这种机制称为线程调度。

线程调度有两种模型:分时调度和抢占式调度。分时调度是指按照执行线上同一维度的时间片轮流分配CPU的使用权。抢占式调度按照优先级分配CPU使用权。

线程优先级
Java JVM默认是抢占式调度,优先级决定了CPU分配顺序。
在这里插入图片描述
图中大写的常量设置线程优先级。

线程休眠
sleep(long millis)方法让线程休眠一段时间把CPU让给其他线程。该方法时静态方法,只能控制当前的线程休眠,休眠结束后,该线程进入等待对列。

螺纹优惠
线程让步时正在执行的线程将CPU让给其他线程,yield()方法。

线程队列跳转
线程可以通过join()方法在某个线程之前执行。

线程安全
多线程共享资源时由于延迟或其他原因导致的错误。

class MyRunnable implements Runnable{
    
    private int total=5;
    @Override
    public void run() {
    
        while (total>=1){
    
            //获取当前线程
            Thread thread=Thread.currentThread();
            //获取线程名
            String th_name=thread.getName();
            //添加延迟
            try {
    
                Thread.sleep(10);
            } catch (InterruptedException e) {
    
                e.printStackTrace();
            }
            System.out.println(th_name+"正在发售第"+total--+"张票");
        }
    }
}


public class MainApp {
    
    public static void main(String[] args) {
    
        Thread myThreadOne1=new Thread(new MyRunnable());
        Thread myThreadOne2=new Thread(new MyRunnable());
        Thread myThreadOne3=new Thread(new MyRunnable());
        myThreadOne1.start();
        myThreadOne2.start();
        myThreadOne3.start();

    }
}


代码模拟了10毫秒的延迟,线程执行的进度是不一样的。
在这里插入图片描述
由于线程都有10毫秒的休眠,出现了很多重复的情况。

Java提供了同步机制,当多个线程使用同一个共享资源时将执行共享资源的代码放在synchronized关键字修饰的代码块中,这个代码块被称作同步代码块。

synchronized 返回值类型 方法名([参数列表]){代码块}

synchronized (obj){
    
    while (total>0){
    
        //获取当前线程
        Thread thread=Thread.currentThread();
        //获取线程名
        String th_name=thread.getName();
        //添加延迟
        try {
    
            Thread.sleep(10);
        } catch (InterruptedException e) {
    
            e.printStackTrace();
        }
        System.out.println(th_name+"正在发售第"+total--+"张票");
    }
}
. . .

相关推荐

额外说明

[已解决]JAVA后台允许匿名App访问Shiro框架Spring框架

1.自定义的Realm <bean id="ShiroRealm" class="com.fh.interceptor.shiro.ShiroRealm" ></bean> 2.配置Shiro Filter 3.效果(不需要登录Java后台,直接访问连

额外说明

常见数据库SQL特性对比:索引和约束

更新日期:2019-10-10。 在上一篇中,列出了 11 种常见数据库对于查询语句的支持情况。接下来我们继续介绍这些数据库产品对于索引和约束的特性比较。 索引 Oracle PostgreSQL SQL Server IBM Db2 MySQL Mar

额外说明

☀️ 学会编程入门必备 C# 最基础知识介绍——带你认识 C# 中的几种循环结构( for & while & do...while)

前言- C# for/foreach 循环- for 流程图 foreach C# while循环- 语法 流程图 C# do...while 循环- 语法 流程图 C# 嵌套循环- 语法 循环控制语句- C# break 语句 语法 流程图 C# co

额外说明

【PHP & MySQL】数据库专题 第八课 表连接

【PHP & MySQL】✔️数据库专题✔️ 第八课 表连接 概述 表连接 内连接 左连接 右连接 全连接 概述 从今天开始, 小白我将带领大家一起来补充一下 数据库的知识. 表连接 表连接 (JOIN) 是在多个表之间通过连接条件. 使表之间发生关联,

额外说明

PHP中安装和使用xdebug

文章目录 前言 配置详解 总结 前言 本文已收录于PHP全栈系列专栏:PHP快速入门与实战 作为一个程序员,千万不要说你没有用过debug工具,不然有点说不过去。xdebug是PHP语言一个强大的利器,用他可以做很多事情。 xdebug是PHP开发者常用

额外说明

C++散列法

散列法是一种搜索算法,它可以根据各元素的值来确定存储位置,然后将位置保管在散列表中,从而实现高速搜索 其中散列表是一种数据结构,能对包含关键字的数据集合高效地执行动态插入、搜索、删除操作。 散列法如果忽略发生冲突(不同的key对应同一散列值)的情况,那么

额外说明

MyBatis框架笔记01:MyBatis初探

目录 一、什么是MyBatis (一)MyBatis概述 (二)ORM工具的基本思想 二、创建数据库与表

额外说明

【抓包工具】配置:Fiddler 设置 APP 抓包成功,微信小程序却无网络问题解决

目录 一、问题情况:微信小程序无网络 二、问题解决:微信小程序无网络 三、问题情况:APP 无网络 四、问题解决:APP 无网络 一、问题情况:微信小程序无网络 fiddler 配置 https 成功后,手机已下载并安装证书: APP 可以抓包成功,但是

额外说明

使用阿里云进行备案踩过的坑

一、引入 作为大学生的我们购买云服务器具有相当的优惠,于是在暑假购买了一台云服务器,在部署了LAMP环境之后就再也没有动过了。上周末采用SSM+Vue和微信做了个小项目,想着部署(虽说直接IP也能看,但是微信小程序需要域名(当然就需要备案啦),另外还是域

额外说明

计算机丢失concrt140.dll文件如何解决?

其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或者损坏了,这时你只需下载这个concrt140.dll文件进行安装(前提是找到适合的版本)

ads via 小工具