前言:

本文将简单的介绍JAVA并发中的线程。

操作系统的多任务(multitasking):计算机在同一刻运行多个程序的能力,即并发。并发执行的进程数目并不是由CPU数目制约的,操作系统将CPU时间片给每一个进程,给人并行处理的感觉。多线程程序在较低层次扩展了多任务的概念:一个程序可以同时处理多个任务。通常,每一个任务称为一个进程。

进程与线程的区别:本质的区别在于每一个进程拥有自己的一整套变量,而线程共享数据。共享数据会在同步时带来风险,然而共享变量使线程之间的通信比进程之间的通信更有效、更容易。与进程相比,线程更加“轻量级”,创建、撤销一个线程比启动新进程的开销要小得多。

一、什么是线程

单独的线程中执行一个任务的简单过程:

1)将任务代码移到实现了Runnable接口的类中:Runnable接口十分简单,只需要实现一个run方法

public  interface Runnable{

   void run();

}

2)由Runnable创建一个Thread对象

Thread thread = new Thread(runnable);

3)启动线程 thread.start();

不要调用Tread类或Runnable对象的run方法。直接调用run方法,只会执行一个线程中的任务,而不会启动新线程。应该调用Thread.run()方法。这样将会创建一个新线程来执行run方法。

二、中断线程

线程终止:当线程的run方法执行方法体中最后一条语句时,并经由执行return语句返回时,或者出现了在方法中没有捕获的异常时,线程终止。在早期Java版本中,有一个stop方法可以被其他线程调用它终止线程,这方法已被弃用,不推荐使用。

现在没有强制停止线程的方法,但可以通过interrupt(中断)方法发送请求终止线程。当线程调用这方法是,线程的中断状态将被置位,这是每一个线程都具有的boolean标志。每个线程都会不时的检查这个标志,以判断线程是否被请求中断。

想要知道当前线程是否被置位,首先应调用静态的Thread.currentThread方法来获得当前线程,然后调用isInterrupt方法:

while(!Thread.currentThread().isInterrupt() && more work to do){
do more work;
}

但是,当一个线程被阻塞,就无法检测中断状态。当阻塞和中断请求碰撞在一起时,会产生InterruptedException。当在一个被阻塞的的线程(线程调用sleep或wait会被阻塞)上调用interrupt时,阻塞调用将会被InterruptedException中断。

没有任何语言方面的需求要求一个被中断的线程应该终止。中断一个线程不过是引起它的注意。被中断的线程可以决定如何响应中断。某些重要的线程应该处理完异常后,继续执行,而不会理会中断。但更普遍的情况是,线程简单的将中断作为一个终止的请求。这种现成的run方法如下:

Runable r = () ->{
try{
...
while(!Thread.currentThread().isInterrupt() && more work to do){
do more work;
}
}catch(InterruptedException e){
//thread was interrupted during sleeo or wiat
}finally{
//cleanup,if required
}
//exiting thr run method terminates the thread
}

如果在每次工作迭代之后都调用sleep方法(或其他的可中断方法),inInterrupt检测既没有必要也没有用处。如果在中断状态被置位是调用sleep方法,线程不会休眠。相反,它将会清除这一状态并抛出InterruptedException异常。

相似的方法:interruptedisInterrupt

interrupted方法是一个静态方法,它检测当前的线程是否被中断,调用interrupted方法会清除该线程的中断状态。

isInterrupt方法是一个实例方法,可用来检测是否有线程被中断,调用这个方法不会改变中断状态。

s

  • void interrupt()

    向线程发送中断请求。将线程中断状态设置为true。如果当前线程被sleepwait调用阻塞,那么InterruptedException异常被抛出

  • static boolean interrupted()

    测试当前线程是否被中断,静态方法。调用这方法会产生另一作用,它将当前线程的中断状态重置为false。

  • boolean isInterrupt()

    测试线程是否被终止,不会改变中断状态。

  • static Thread currentThread()

    返回代表当前执行线程的Thread对象。

三、线程状态

线程有六种状态:

  • New 新创建
  • Runnable 可运行
  • Blocked 被阻塞
  • Waiting 等待
  • Timed waiting 计时等待
  • Terminated 被终止

通过调用getState方法可确定一个线程的当前状态

  1. 新建状态

    ​ 当new Thread一个新线程时,改线程还没有还是运行,意味这它的状态是new,当线程处于这一状态时,程序不会开始执行线程中的代码。

    Thread thread = new Thread(runnable)

  2. 可运行线程

    ​ 当调用线程的start方法,线程处于runnable可运行状态。要注意,一个可运行的线程可能正在运行也可能没有运行,线程的运行取决于操作系统给线程提供运行的时间。系统会从处于可运行状态的线程队列中调度线程,为其提供CPU时间片。

    ​ 我们将这一状态的线程称为可运行而不是运行。一旦一个线程开始运行,它不必始终保持运行。运行中的线程被中断,为的是让其他线程获得运行机会。

    ​ 线程调度的细节依赖于操作系统提供的服务。现在所有的桌面以及服务器操作系统都使用抢占式调度。抢占式调度系统给每一个可运行线程一个时间片来执行程序。当时间片用完,操作系统剥夺该线程的运行权,并给另一个线程运行机会。在选择下一个线程时,操作系统还会考虑线程的优先级。

  3. 被阻塞和等待线程

    ​ 当线程处于被阻塞或等待状态时,它不运行任何代码且消耗最少的资源。

    • 当一个线程试图获取一个内部的对象锁(而不是java.util.concurrent库中的锁),而该锁被其他线程持有,则该线程进入阻塞状态。只有当该锁被持有的线程释放时,所有请求该锁的线程变为非阻塞状态,并竞争该锁。
    • 当线程等待另一个线程通知调度器的一个条件时,它自己进入等待状态。在调用Object.wait方法或Thread,jion方法,或者是等待java.util.concurrent库中的LockCondition时,就会出现线程等待。
    • 有几个方法中有一个超时参数。调用他们导致线程进入计时等待状态。这一状态将保持到超时期满或者收到适当的通知。
  4. 被终止的线程

    线程有如下两个原因之一而被终止:

    • 因为run方法正常退出而自然死亡

    • 因为一个没有捕获的异常终止了run方法而意外死亡

四、线程属性

线程的属性包括:线程优先级,守护线程,线程组以及处理未捕获异常的处理器。

  • 线程优先级

    ​ 在Java中,每一个线程有一个优先级,默认情况加,一个线程继承它的父线程的优先级。

    ​ 可用setPriority方法提高或降低任何一个线程的优先级。。可以将优先级设置在MIN_PRIORITY(1)与MAX_PRIORITY(10)之间的任何值。NORM_PRIORITY被定义为5。每当线程调度器有机会选择新线程时,它首先选择具有较高优先级的线程。但是,线程的优先级是高度依赖于操作系统的。当虚拟机依赖于宿主机平台的线程实现机制时,Java线程的优先级被映射到宿主机平台的优先级上。

    ​ 在设置线程优先级时,要防止线程饿死。每当调度器决定运行一个新线程时,首先会在具有高优先级的线程中进行选择,尽管这样会使低优先级的线程完全饿死。

  • 守护线程

    通过调用:

    t.setDaemon(true);

    将线程设置为守护线程。

    守护线程的唯一作用就是为其他线程提供服务。当只剩下守护线程时。虚拟机就会退出。

  • 未捕获异常处理器

    ​ 线程run方法不能抛出任何的受查异常,而受查异常又会导致线程终止,此时县城就死亡了。有有种办法,不需要任何catch子句来处理被传播的异常。在线程死亡之前,异常被传递到一个用于捕获异常的处理器。

    ​ 捕获异常的处理器必须属于一个实现Thread.UncaughtExceptionHandler接口的类,接口内只有一个方法。

    void uncaughtException(Thread t, Throwable e);

    ​ 可以用setUncaughtExceptionHandler方法为任何线程安装处理器。也可以用setDefauktUncaughtHandler为所有线程安装一个默认的处理器。如果没有,默认的处理器为空。

Java并发(一):线程的更多相关文章

  1. Java 并发 中断线程

    Java 并发 中断线程 @author ixenos 对Runnable.run()方法的三种处置情况 1.在Runnable.run()方法的中间中断它 2.等待该方法到达对cancel标志的测试 ...

  2. Java 并发编程 | 线程池详解

    原文: https://chenmingyu.top/concurrent-threadpool/ 线程池 线程池用来处理异步任务或者并发执行的任务 优点: 重复利用已创建的线程,减少创建和销毁线程造 ...

  3. java并发编程 线程基础

    java并发编程 线程基础 1. java中的多线程 java是天生多线程的,可以通过启动一个main方法,查看main方法启动的同时有多少线程同时启动 public class OnlyMain { ...

  4. Java并发1——线程创建、启动、生命周期与线程控制

    内容提要: 线程与进程 为什么要使用多线程/进程?线程与进程的区别?线程对比进程的优势?Java中有多进程吗? 线程的创建与启动 线程的创建有哪几种方式?它们之间有什么区别? 线程的生命周期与线程控制 ...

  5. java并发:线程同步机制之Volatile关键字&原子操作Atomic

    volatile关键字 volatile是一个特殊的修饰符,只有成员变量才能使用它,与Synchronized及ReentrantLock等提供的互斥相比,Synchronized保证了Synchro ...

  6. java并发:线程池、饱和策略、定制、扩展

    一.序言 当我们需要使用线程的时候,我们可以新建一个线程,然后显式调用线程的start()方法,这样实现起来非常简便,但在某些场景下存在缺陷:如果需要同时执行多个任务(即并发的线程数量很多),频繁地创 ...

  7. java并发:线程同步机制之Lock

    一.初识Lock Lock是一个接口,提供了无条件的.可轮询的.定时的.可中断的锁获取操作,所有加锁和解锁的方法都是显式的,其包路径是:java.util.concurrent.locks.Lock, ...

  8. Java并发编程:线程间通信wait、notify

    Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...

  9. Java并发编程:线程和进程的创建(转)

    Java并发编程:如何创建线程? 在前面一篇文章中已经讲述了在进程和线程的由来,今天就来讲一下在Java中如何创建线程,让线程去执行一个子任务.下面先讲述一下Java中的应用程序和进程相关的概念知识, ...

  10. Java并发3-多线程面试题

    1) 什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速. 2) 线程和进程有什 ...

随机推荐

  1. 01 . OpenResty简介部署,优缺点,压测,适用场景及用Lua实现服务灰度发布

    简介 OpenResty 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库.第三方模块以及大多数的依赖项.用于方便地搭建能够处理超高并发.扩展性极高的动态 ...

  2. Iptables 下 SNAT、DNAT和MASQUERADE三者之间的区别

    Iptables 中可以灵活的做各种网络地址转换(NAT,Network Address Translation) 网络地址转换(NAT)主要有两种:SNAT 和 DNAT,但是也有一种特例 MASQ ...

  3. kubernetes-介绍与特性

    1. kubernetes概述 1) kubernetes是什么 2) kubernetes能做什么 3) kubernetes特性 4) kubernetes集群架构与组件 5) kubernete ...

  4. install Wine + WeChat in Fedora 31

    install Wine + WeChat in Fedora 31 dnf -y install dnf-plugins-core dnf config-manager --add-repo htt ...

  5. monolog handler用哪个

    Handlers 记录日志到文件与系统日志(syslog) StreamHandler:记录日志到任何 PHP stream,用它来记录到文件. RotatingFileHandler: 每天一个文件 ...

  6. zabbix:以主动模式添加一台受监控主机 (zabbix5.0)

    一,zabbix被动模式和主动模式的区别? zabbix-agent默认的模式是被动模式, zabbix agent被动地接受zabbix server发来的指令, 获取数据后再返回给zabbix s ...

  7. 本地ssh快速登录 ssh免密登录

    每次登录都要ssh -p wang@xx.xx.xx.xx 虽然做了公钥验证 https://www.cnblogs.com/php-linux/p/10795913.html 不需要输入密码,但是每 ...

  8. buuctf-misc-[BJDCTF 2nd]圣火昭昭-y1ng 1

    开局一张图片,flag全靠猜,那这个是不是和outguess工具有关呢?于是我们显示查看了图片的详细信息 看到是新佛曰,于是我们用新佛曰论禅解密:http://hi.pcmoe.net/buddha. ...

  9. 渗透测试之GoogleHack

    GoogleHack 1,介绍: 使用google等搜索引擎对某些特定的网络主机漏洞(一般是服务器上的脚本漏洞)进行搜索,都能达到快速找到1漏洞的目的,然而,google相对百度讲,没有广告,搜索引擎 ...

  10. springboot错误统一处理

    1,对于404,500这类错误,可以直接新建public/error目录 ,在error目录 中新建404.html, 500.html或5xx.html,springboot会自动跳转到这些静态页面 ...