1.启动线程的三种方式:

  1.1继承Thread类

    public static class UseThread extends Thread {
public void run() {
System.out.println("thread run 执行!");
}
}

  启动线程:

UseThread ut = new UseThread();
ut.start();

  1.2实现Runable接口

    public static class UseRun implements Runnable {
@Override
public void run() {
System.out.println("runable run 执行!");
}
}

  启动线程

UseRun ur = new UseRun();
new Thread(ur).start();

  1.3实现Callable接口

    public static class UseCall implements Callable<String> {
@Override
public String call() throws Exception {
return "callable call 执行!";
}
}

  启动线程

  它是有返回值的,需要用FutureTask来包装,如:

UseCall uc = new UseCall();
FutureTask<String> ft = new FutureTask<>(uc);
new Tread(ft).start();
System.out.println(ft.get());

  返回值需要用Future的get方法来获取。 执行结果:

callable call 执行!

2.使用interrupt来中断线程

先看一段代码

public class InterruptTest01 {

    public static class m1 implements Runnable {

        public void run() {
try {
System.out.println("in run() - 睡眠20秒");
Thread.sleep(20000);
System.out.println("in run() - 线程唤醒");
} catch (Exception e) {
System.out.println("in run() - 线程睡眠中被打断了");
// 如果没有return,线程不会实际被中断,它会继续打印下面的信息
System.out.println("t线程sleep中被打断后中断标志位状态:" + Thread.interrupted());
return;
}
System.out.println("in run() - 线程正常的消亡了");
}
} public static void main(String[] args) {
m1 si = new m1();
Thread t = new Thread(si);
// 开启t线程
t.start();
System.out.println("调用interrupt方法前,t线程的中断状态:" + t.isInterrupted());
try {
// 仅仅是做标记
t.interrupt();
System.out.println("调用interrupt方法后,t线程的中断状态:" + t.isInterrupted());
// 主线程休眠2秒,从而确保刚才启动的线程有机会执行一段时间
Thread.sleep(2000);
} catch (InterruptedException e) {
System.err.println("主线程catch块出问题了");
}
System.out.println("in main() - 主线程终止了");
} }

运行的结果:

调用interrupt方法前,t线程的中断状态:false
调用interrupt方法后,t线程的中断状态:true
in run() - 睡眠20秒
in run() - 线程睡眠中被打断了
t线程sleep中被打断后中断标志位状态:false
in main() - 主线程终止了

分析:

分析:Thread.sleep(2000)这个方法需放在interrupt方法之后,如果放在之前,会出现中断标志位全为false的情况。如果只是单纯的调用interrupt()方法,线程并没有实际被中断,会继续往下执行。

比如这样:

public class InterruptTest01 {

    public static class m1 implements Runnable {

        public void run() {
while (true){
System.out.println("我是不会中断的了");
}
}
} public static void main(String[] args) {
try {
m1 si = new m1();
Thread t = new Thread(si);
// 开启t线程
t.start();
System.out.println("调用interrupt方法前,t线程的中断状态:" + t.isInterrupted());
// 仅仅是做标记
t.interrupt();
System.out.println("调用interrupt方法后,t线程的中断状态:" + t.isInterrupted());
// 主线程休眠2秒,从而确保刚才启动的线程有机会执行一段时间
Thread.sleep(2000);
} catch (InterruptedException e) {
System.err.println("主线程catch块出问题了");
}
System.out.println("in main() - 主线程终止了");
} }

它的运行结果就是自旋,应当在run方法中加上中断标志位的判断,如下:

public static class m1 implements Runnable {
public void run() {
while (true){
if(Thread.interrupted()){
System.out.println("我竟然中断了");
return;
}
System.out.println("我是不会中断的了");
}
}
}

再次运行的结果:

调用interrupt方法前,t线程的中断状态:false
调用interrupt方法后,t线程的中断状态:true
我竟然中断了
in main() - 主线程终止了

3.待决中断

意思就是:如果线程在调用sleep()方法前被中断,那么该中断称为待决中断,它会在刚调用sleep()方法时,立即抛出InterruptedException异常。

如下:

public class PendingInterruptTest {

    public static void main(String[] args) {
Thread.currentThread().interrupt();
// 获取当前时间
long startTime = System.currentTimeMillis();
try {
Thread.sleep(2000);
System.out.println("主线程没有被打断");
} catch (InterruptedException x) {
System.out.println("主线程被打断,进入catch块");
}
// 计算中间代码执行的时间
System.out.println("时间差 =" + (System.currentTimeMillis() - startTime));
} }

运行代码的结果:

主线程被打断,进入catch块
时间差 =1

4.interrupted和isInterrupted的区别?

首先看一段代码

public class InterruptTest01 {

    public static class m1 implements Runnable {
public void run() {
System.out.println("我是不会中断的了");
}
} public static void main(String[] args) {
try {
m1 si = new m1();
Thread t = new Thread(si);
// 开启t线程
t.start();
System.out.println("调用interrupt方法前0,t线程的中断状态:" + t.interrupted());
t.interrupt();
System.out.println("调用interrupt方法后1,t线程的中断状态:" + t.interrupted());
System.out.println("调用interrupt方法后2,t线程的中断状态:" + t.interrupted());
// 主线程休眠2秒,从而确保刚才启动的线程有机会执行一段时间
Thread.sleep(2000);
} catch (InterruptedException e) {
System.err.println("主线程catch块出问题了");
}
System.out.println("in main() - 主线程终止了");
} }

运行的结果为:

调用interrupt方法前0,t线程的中断状态:false
调用interrupt方法后1,t线程的中断状态:false
调用interrupt方法后2,t线程的中断状态:false
我是不会中断的了
in main() - 主线程终止了

分析:

结果竟然都是false,可见thread 线程并没有停止,而且调用 thread.interrupted() 结果是两个 false 表示线程一直在运行过程中。官方解释:当前线程是指运行 this.interrupted() 方法的线程 。也就是说,当前线程并不是 t,并不是因为 t 调用了 interrupted() 方法就是当前线程。当前线程一直是 main 线程,它从未中断过,所以打印结果就是两个 false。

改变一下代码:

public class InterruptTest01 {

    public static class m1 implements Runnable {
public void run() {
System.out.println("我是不会中断的了");
}
} public static void main(String[] args) {
try {
m1 si = new m1();
Thread t = new Thread(si);
// 开启t线程
t.start();
System.out.println("调用interrupt方法前0,t线程的中断状态:" + Thread.interrupted());
Thread.currentThread().interrupt();
System.out.println("调用interrupt方法后1,t线程的中断状态:" + Thread.interrupted());
System.out.println("调用interrupt方法后2,t线程的中断状态:" + Thread.interrupted());
// 主线程休眠2秒,从而确保刚才启动的线程有机会执行一段时间
Thread.sleep(2000);
} catch (InterruptedException e) {
System.err.println("主线程catch块出问题了");
}
System.out.println("in main() - 主线程终止了");
} }

结果:

调用interrupt方法前0,t线程的中断状态:false
调用interrupt方法后1,t线程的中断状态:true
调用interrupt方法后2,t线程的中断状态:false
我是不会中断的了
in main() - 主线程终止了

分析:

从上述结果中可以看出,方法 interrupted() 的确判断出当前线程是否已经停止,但是为什么第 2 个布尔值是 false 呢?文档中说的很详细,interrupted() 方法具有清除状态的功能,所以第二次的时候返回值是 false。

isInterrupt()方法代码

public static void main(String[] args) {
try {
Thread t = Thread.currentThread();
System.out.println("调用interrupt方法前0,t线程的中断状态:" + t.isInterrupted());
t.interrupt();
System.out.println("调用interrupt方法后1,t线程的中断状态:" + t.isInterrupted());
System.out.println("调用interrupt方法后2,t线程的中断状态:" + t.isInterrupted());
// 主线程休眠2秒,从而确保刚才启动的线程有机会执行一段时间
Thread.sleep(2000);
System.out.println("还在输出吗?");
} catch (InterruptedException e) {
System.err.println("主线程catch块出问题了");
}
System.out.println("in main() - 主线程终止了");
}

结果:

调用interrupt方法前0,t线程的中断状态:false
主线程catch块出问题了
调用interrupt方法后1,t线程的中断状态:true
调用interrupt方法后2,t线程的中断状态:true
in main() - 主线程终止了

分析:

线程一旦被中断,isInterrupted()方法便会返回true,而一旦sleep()方法抛出异常,它将清空中断标志,此时isInterrupted()方法将返回false

总结以上:

总结:interrupted():测试 当前线程 是否已经是中断状态,执行后具有清除状态功能。isInterrupted():测试线程 Thread 对象 是否已经是中断状态,但不清除状态标志。

并发编程大师系列之:线程的定义和中断 interrupt的更多相关文章

  1. 并发编程大师系列之:Synchronized的类锁和对象锁

    说到并发编程,感觉跟大多数人一样,谈之色变,说它简单把,其实很有内容,说难吧,用起来也挺容易,最近我硬着头皮,决心要把并发编程好好的搞一遍.以前,面试的时候,面试官问,并发编程会吗?嗯,接触过,就加一 ...

  2. 并发编程大师系列之:wait/notify/notifyAll/condition

    1. wait().notify()和notifyAll()方法是本地方法,并且为final方法,无法被重写. 2. 调用某个对象的wait()方法能让当前线程阻塞,并且当前线程必须拥有此对象的mon ...

  3. 并发编程大师系列之:CountDownLatch和Join

    业务场景描述:假设一条流水线上有三个工作者:worker1,worker2,worker3.有一个任务的完成需要他们三者协作完成,worker3可以开始这个任务的前提是worker1和worker2完 ...

  4. Java 并发编程——Executor框架和线程池原理

    Eexecutor作为灵活且强大的异步执行框架,其支持多种不同类型的任务执行策略,提供了一种标准的方法将任务的提交过程和执行过程解耦开发,基于生产者-消费者模式,其提交任务的线程相当于生产者,执行任务 ...

  5. Java 并发编程——Executor框架和线程池原理

    Java 并发编程系列文章 Java 并发基础——线程安全性 Java 并发编程——Callable+Future+FutureTask java 并发编程——Thread 源码重新学习 java并发 ...

  6. linux高级编程基础系列:线程间通信

    linux高级编程基础系列:线程间通信 转载:原文地址http://blog.163.com/jimking_2010/blog/static/1716015352013102510748824/ 线 ...

  7. Java并发编程:如何创建线程?

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

  8. 【转】Java并发编程:如何创建线程?

    一.Java中关于应用程序和进程相关的概念 在Java中,一个应用程序对应着一个JVM实例(也有地方称为JVM进程),一般来说名字默认是java.exe或者javaw.exe(windows下可以通过 ...

  9. python并发编程之进程、线程、协程的调度原理(六)

    进程.线程和协程的调度和运行原理总结. 系列文章 python并发编程之threading线程(一) python并发编程之multiprocessing进程(二) python并发编程之asynci ...

随机推荐

  1. noVNC 安装、配置与使用

    最近项目中使用到了远程终端操控,从各方找到了noVNC这个神奇的家伙,废话不多说,开始介绍它的安装配置与使用. 1. 下载noNVC 好多渠道可以下载到noVNC,可以直接访问noVNC的官方网页ht ...

  2. cmake vs qmake

    qmake 是为 Qt 量身打造的,使用起来非常方便 cmake 使用上不如qmake简单直接,但复杂换来的是强大的功能 内置的 out-of source 构建.(目前QtCreator为qmake ...

  3. SFTP客户端与服务端

    什么是 SFTP ? 在了解 SFTP 之前,我们先看看什么是 FTP . FTP( File Transfer Protocol )文件传输协议,是一种常用来在两终端系统之间传输文件的方法. SFT ...

  4. Spring Boot开启Druid数据库监控功能

    Druid是一个关系型数据库连接池,它是阿里巴巴的一个开源项目.Druid支持所有JDBC兼容的数据库,包括Oracle.MySQL.Derby.PostgreSQL.SQL Server.H2等.D ...

  5. hdu 5418 题解

    第一眼看到这题,哇,这不是我刚做完的题吗?大水题!然后 这题表面很水,实际上有点坑. 题意 求经过 $ 1 - n $(不能遗漏) 并且回到 $ 1 $ 的最短路. 在看这题之前我们可以来看下这题 最 ...

  6. 考试应对(Java语法速览)

    1.从命令行输入数据 格式:Scanner reader=new Scanner(System.in); 此reader对象可以使用的方法:nextBoolean(),nextByte(),nextS ...

  7. C++中的构造函数与析构函数及组合类的调用

    // 构造函数与析构函数及类的组合 #include "stdafx.h"#include <iostream>using namespace std; //枚举enu ...

  8. PEB TEB结构体使用

    PEB TEB结构体使用一个可执行文件被OS加载到内存,并处理完成相关的模块加载,导入表处理……及其他必须处理后,形成一个进程.在OS内核中保存有一份关于这个进程的身份证信息,就是平常看到的HANDL ...

  9. Linux入职基础-1.2_U盘安装RedHat5具体步骤

    从U盘安装RedHat5具体步骤 从U盘安装RedHat Linux的具体步骤: 准备工作: RHEL_5.6_i386_DVD.ISO文件 具体步骤: 1.解压并用ultraiso软件打开rhel- ...

  10. Matlab匿名函数,向量化和预分配,函数的函数,P码文件

    匿名函数: 匿名函数是不存储在程序文件中.但与数据类型是 function_handle 的变量相关的函数.匿名函数可以接受输入并返回输出,就像标准函数一样.但是,它们可能只包含一个可执行语句. 例如 ...