一、线程生命周期

线程被创建启动以后,他既不是一启动就进入执行状态,也不是一直处于执行状态,在线程的生命周期中,它要经过新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)五种状态

1、新建状态

当程序使用new关键字创建了一个线程后,该线程就处于新建状态

2、就绪状态

当线程对象调用了start()方法之后,该线程就处于就绪状态,java虚拟机会为其创建方法调用栈和程序计数器。

这个状态中的线程并没有开始执行线程,只是表示该线程可以运行了,至于何时运行,取决于JVM线程调度器调度。

3、运行状态

如果处于就绪状态的线程获得了CPU,开始执行run()方法的线程执行体,则该线程处于运行状态。

4、阻塞状态

当运行状态的线程发生如下情况时,线程会进入阻塞状态:

(1)线程调用sleep()方法主动放弃所占用的处理器资源。

(2)线程调用了一个阻塞式IO方法,在该方法返回之前,该线程被阻塞

(3)线程试图获得一个同步监视器,但该同步监视器正被其他线程所持有。

(4)线程在等待某个通知(notify)

(5)程序调用了线程的suspend()方法将线程挂起,这个方法在jdk1.6中已经过时,它容易导致死锁,不建议使用。

针对上面阻塞状态,当发生下面特定情况可以解除阻塞状态:

(1)sleep()方法经过了指定时间。

(2)阻塞式IO方法已经返回

(3)线程成功获得了一个同步监视器。

(4)线程在等待某个通知时,其他线程发出了一个通知

(5)处于挂起的线程被调用了resume()恢复方法

5、线程死亡

线程结束后就处于死亡状态,有三种结束方式:

(1)run()或call()方法执行完成,线程正常结束

(2)线程抛出一个未捕获的Exception或者Error

(3)直接调用线程的stop()方法结束线程——容易死锁,不建议使用

isAlive()方法可以判断线程是否死亡,当处于就绪、运行、阻塞状态时返回true,处于新建、死亡状态时返回false。

已经死亡的线程不能重新启动,否则引发IllegalThreadStateException。

二、控制线程

java线程提供了一些简便的工具方法,利用这些方法可以很好的控制线程

1、join()

join()方法:让一个线程等待一个线程完成。

package threadtest;
public class ThreadTest implements Runnable {
@Override
public void run() {
for(int i=0;i<30;i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
} } public static void main(String[] args) throws InterruptedException { ThreadTest target1 = new ThreadTest();
Thread t1 = new Thread(target1,"t1");
t1.start();
for(int i=0;i<30;i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
//开始主线程和t1线程并发执行,当main线程的i到15时,调用了t1线程的join方法,
//此时主线程等待t1线程,直到t1结束时才跑main,
//join后,主线程处于阻塞状态
if(i == 15) {
t1.join();
}
}
} }

2、线程睡眠 sleep()

如果需要让当前线程暂停一段时间,则可以使用sleep()方法

package threadtest;

import java.time.LocalTime;

public class ThreadTest implements Runnable {

    @Override
public void run() {
for(int i=0;i<30;i++) {
System.out.println(Thread.currentThread().getName() + " " + i +" "+ LocalTime.now());
if(i == 15){
try {
Thread.sleep(10000);//10s
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} public static void main(String[] args) throws InterruptedException { ThreadTest target1 = new ThreadTest();
Thread t1 = new Thread(target1,"t1");
t1.start();
}
}

3、线程让步 yield()

yield()方法会让线程直接进入就绪状态,主要作用就是让当前线程暂停一下。完全有可能线程yield()后,线程调度器又将该线程调度出来执行。

yield()暂停后,只有优先级与当前线程相同或者优先级比当前线程更高的处于就绪状态的线程才有机会获得执行机会。

package threadtest;

import java.time.LocalTime;

public class ThreadTest implements Runnable {
@Override
public void run() {
for(int i=0;i<30;i++) {
System.out.println(Thread.currentThread().getName() + " " + i +" "+ LocalTime.now());
if(i == 15){
Thread.yield();//线程让步
}
}
} public static void main(String[] args) throws InterruptedException { ThreadTest target1 = new ThreadTest();
Thread t1 = new Thread(target1,"t1");
t1.start();
for(int i=0;i<10;i++) {
System.out.println(Thread.currentThread().getName() + " " + i +" "+ LocalTime.now());
}
}
}

sleep()和yield()方法的区别

(1)sleep暂停后会给其他线程机会,不会理会其他线程的优先级,但yield只给优先级相同或者更高的线程机会

(2)sleep将线程转为阻塞状态,yield将线程转为就绪状态

(3)sleep方法声明抛出了InterruptedException异常,所以用sleep要么捕捉该异常,要么抛出该异常。

(4)sleep比yield有更好的移植性,通常不建议使用yield方法来控制并发线程的执行

线程的优先级

每个线程执行时都有一定的优先级,优先级高的线程能获得更多的执行机会。每个线程的默认优先级与创建它的父线程优先级相同。默认情况下,main线程具有普通优先级

Thread类中 setPriority(int newPriority)和getPriority()方法分别设置和获取线程的优先级。

setPriority(int newPriority)的参数是一个整数,范围1-10;也可以是三个静态常量

MAX_PRIORITY:10

MIN_PRIORITY:1

NORM_PRIORITY:5

package threadtest;

import java.time.LocalTime;

public class ThreadTest implements Runnable {
@Override
public void run() {
for(int i=0;i<30;i++) {
System.out.println(Thread.currentThread().getName() + " " + i +" "+ LocalTime.now());
if(i == 15){
Thread.yield();
}
}
} public static void main(String[] args) throws InterruptedException { ThreadTest target1 = new ThreadTest();
Thread t1 = new Thread(target1,"t1");
Thread t2 = new Thread(target1,"t2");
t2.setPriority(Thread.MAX_PRIORITY);//设置优先级
t1.start();
t2.start();
}
}

java并发编程基础—生命周期与线程控制的更多相关文章

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

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

  2. Java并发编程基础

    Java并发编程基础 1. 并发 1.1. 什么是并发? 并发是一种能并行运行多个程序或并行运行一个程序中多个部分的能力.如果程序中一个耗时的任务能以异步或并行的方式运行,那么整个程序的吞吐量和可交互 ...

  3. 并发-Java并发编程基础

    Java并发编程基础 并发 在计算机科学中,并发是指将一个程序,算法划分为若干个逻辑组成部分,这些部分可以以任何顺序进行执行,但与最终顺序执行的结果一致.并发可以在多核操作系统上显著的提高程序运行速度 ...

  4. Java并发编程(您不知道的线程池操作), 最受欢迎的 8 位 Java 大师,Java并发包中的同步队列SynchronousQueue实现原理

    Java_并发编程培训 java并发程序设计教程 JUC Exchanger 一.概述 Exchanger 可以在对中对元素进行配对和交换的线程的同步点.每个线程将条目上的某个方法呈现给 exchan ...

  5. Java并发编程--基础进阶高级(完结)

    Java并发编程--基础进阶高级完整笔记. 这都不知道是第几次刷狂神的JUC并发编程了,从第一次的迷茫到现在比较清晰,算是个大进步了,之前JUC笔记不见了,重新做一套笔记. 参考链接:https:// ...

  6. Java并发编程(您不知道的线程池操作)

    Java并发编程(您不知道的线程池操作) 这几篇博客,一直在谈线程,设想一下这个场景,如果并发的线程很多,然而每个线程如果执行的时间很多的话,这样的话,就会大量的降低系统的效率.这时候就可以采用线程池 ...

  7. 【Java并发编程】之二:线程中断

    [Java并发编程]之二:线程中断 使用interrupt()中断线程 ​ 当一个线程运行时,另一个线程可以调用对应的Thread对象的interrupt()方法来中断它,该方法只是在目标线程中设置一 ...

  8. java并发编程笔记(七)——线程池

    java并发编程笔记(七)--线程池 new Thread弊端 每次new Thread新建对象,性能差 线程缺乏统一管理,可能无限制的新建线程,相互竞争,有可能占用过多系统资源导致死机或者OOM 缺 ...

  9. java并发编程笔记(五)——线程安全策略

    java并发编程笔记(五)--线程安全策略 不可变得对象 不可变对象需要满足的条件 对象创建以后其状态就不能修改 对象所有的域都是final类型 对象是正确创建的(在对象创建期间,this引用没有逸出 ...

随机推荐

  1. GPU编程和流式多处理器(二)

    GPU编程和流式多处理器(二) 2. 整数支持 SM具有32位整数运算的完整补充. 加法运算符的可选否定加法 乘法与乘法加法 整数除法 逻辑运算 条件码操作 to/from浮点转换 其它操作(例如,S ...

  2. 『动善时』JMeter基础 — 40、JMeter中ForEach控制器详解

    目录 1.什么是逻辑控制器 2.ForEach控制器介绍 3.ForEach控制器的使用 (1)测试计划内包含的元件 (2)获取学院列表请求内容 (3)JSON提取器内容 (4)ForEach控制器内 ...

  3. Java设计模式(4:里氏替换原则和合成复用原则详解

    一.里氏替换原则 如果说实现开闭原则的关键步骤就是抽象化,那么基类(父类)和子类的继承关系就是抽象化的具体实现,所以里氏替换原则就是对实现抽象化的具体步骤的规范.即:子类可以扩展基类(父类)的功能,但 ...

  4. Firfox、Chrome之python-selenium环境搭建

    公共步骤: 一.文件下载 下载地址: python安装包:https://www.python.org/getit/ PyCharm 安装包:http://www.jetbrains.com/pych ...

  5. js正则中文

    hi,大家好 今天跟小伙伴们浅谈以下如何用正则表示中文以及如何去运用.众所周知中文在计算机中是不能进行存储的.那我们是以什么办法让我们和计算机进行更好的沟通呢?常用的几种中文编码格式utf-8编码ut ...

  6. 让Github畅通无阻,FastGithub1.0.0发布

    前言 我近半年来被github的抽风虐得没脾气了,虽然我有代理的方式来上网,但代理速度并不理想,而且有时代理服务一起跟着抽风.这时候,我会搜索"github访问不了"相关题材,其中 ...

  7. 【二分 贪心】覆盖问题 BZOJ1052 HAOI2007

    覆盖问题 bzoj1052 题目来源:HAOI 2007 题目描述 某人在山上种了N棵小树苗.冬天来了,温度急速下降,小树苗脆弱得不堪一击,于是树主人想用一些塑料薄膜把这些小树遮盖起来,经过一番长久的 ...

  8. Linux 的ftp服务未启用怎么办

    1.检查是否安装ftp相关的rpm包(如出现下面提示证明是安装过相关rpm包的) [root@rac1 ~]# which vsftpd    /usr/sbin/vsftpd    [root@ra ...

  9. Android开发回收bitmap引发Canvas: trying to use a recycled bitmap错误处理

    当你的应用由于加载大量图片出现OOM异常时,肯定会上网搜索关于OOM的文章,并导求相应的解决方案,比如压缩图片大小,或手动回收资源什么的.在这里我们不讨论图片压缩或缓冲这些方法,而是讨论一下手动回收B ...

  10. 21、nginx之ngx_http_proxy_module模块

    Nginx 的代理功能是通过 ngx_http_proxy_module 模块来实现的.默认在安装 Nginx 时已经安装了ngx_http_proxy_module模 块,因此可直接使用 ngx_h ...