前言:

本文将简单的介绍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. C++重载>>和<<(输入和输出运算符)详解

    转载:http://c.biancheng.net/view/2311.html 在C++中,标准库本身已经对左移运算符<<和右移运算符>>分别进行了重载,使其能够用于不同数据 ...

  2. P5322 排兵布阵解题报告

    本想在洛谷上交篇题解的,结果发现交不了,所以只能在这边写了... 作为一个蒟蒻,看到省选题,第一眼考虑怎么打暴力 我们可以分情况考虑 当\(s==1\)的时候 我们可以把他当成一个\(01\)背包,背 ...

  3. DevOps元素周期表——1号元素 Gitlab

    DevOps元素周期表--1号元素 Gitlab GitLab 是由 GitLab Inc.开发,一款基于 Git 的完全集成的软件开发平台(fully integrated software dev ...

  4. 099 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 03 编写并测试Student类

    099 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 03 编写并测试Student类 本文知识点:编写并测试Subject类 说明: ...

  5. 多测师讲解selenium _携程选票定位练习_高级讲师肖sir

    打开携程网 from selenium import webdriverfrom time import sleepfrom selenium.webdriver.common.keys import ...

  6. MeteoInfo家族的新产品:MeteoInfoLab

    为了更方便地处理各种数据并绘图,尝试开发了一个新的软件产品MeteoInfoLab,软件设计上参考了MatLab和Spider.软件以脚本程序和命令行交互为主,基于MeteoInfo库并利用Jytho ...

  7. Android开发Settings源码分析之主界面加载(二)

    现在都说互联网寒冬,其实只要自身技术能力够强,咱们就不怕!我这边专门针对Android开发工程师整理了一套[Android进阶学习视频].[全套Android面试秘籍].[Android知识点PDF] ...

  8. 【C语言教程】“双向循环链表”学习总结和C语言代码实现!

    双向循环链表 定义 双向循环链表和它名字的表意一样,就是把双向链表的两头连接,使其成为了一个环状链表.只需要将表中最后一个节点的next指针指向头节点,头节点的prior指针指向尾节点,链表就能成环儿 ...

  9. 扫描仪扫描文件处理-Photoshop批处理无响应问题

    问题描述:Photoshop批处理时候卡死.卡住.无响应问题(出现在处理60M及以上TIFF文件的时候) 解决办法: 调整系统虚拟内存见<扫描-Photoshop批处理内存不足问题解决> ...

  10. 【图论】USACO07NOV Cow Relays G

    题目大意 洛谷链接 给定一张\(T\)条边的无向连通图,求从\(S\)到\(E\)经过\(N\)条边的最短路长度. 输入格式 第一行四个正整数\(N,T,S,E\),意义如题面所示. 接下来\(T\) ...