java多线程Thread的实现方法代码详解
作者:中华雪碧 发布时间:2022-01-03 01:02:28
之前有简单介绍过java多线程的使用,已经Thread类和Runnable类,为了更好地理解多线程,本文就Thread进行详细的分析。
start()
我们先来看看API中对于该方法的介绍:
使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
结果是两个线程并发地运行;当前线程(从调用返回给 start 方法)和另一个线程(执行其 run 方法)。
多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。
用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。通过调用Thread类的 start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行run()方法,这里方法 run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止。
start方法是开启线程的方法,使用后java会创建一个新的线程执行run里的方法。这是一个小demo:
for(int i=0;i<3;i++){
Thread t= new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" start");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" end");
}
});
t.start();
}
System.out.println("it is over");
执行结果:
it is over
Thread-1 start
Thread-0 start
Thread-2 start
Thread-0 end
Thread-1 end
Thread-2 end
由于多线程是有随机性的,所以每次的结果可能都不一样,这一点也是我们需要注意的,线程的执行顺序和调用顺序并不一致。
run()
run方法就是调用Thread设置的Runnable的run方法,将上面的demo进行修改:
for(int i=0;i<3;i++){
Thread t= new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" start");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" end");
}
});
t.run();
}
System.out.println("it is over");
执行结果:
main start
main end
main start
main end
main start
main end
it is over
run方法的直接结果和start有很大的差别,完全是按顺序执行,并没有开启新线程。
stop()
stop方法是强制停止线程的执行,是非安全的,不要使用此方法。在调用stop时, 会对锁定的资源进行释放,但这种释放是非一致的,容易引起程序问题。如果想要控制线程的停止,可以使用自定义变量来判断或者isInterrupted()方法:
class Thread1 extends Thread {
@Override
public void run() {
//判断线程体是否运行
while (!isInterrupted()) {
// Do Something
}
}
}
interrupt()
interrupt的作用是通知线程,你已经被中断的,但具体的中断执行需要在线程自定义处理,甚至你可以不理会继续执行。具体的中孤单是会线程执行join、wait、sleep方法时,抛出InterruptedException。
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" start");
try {
for(int i=0;i<100000;i++){
System.out.println(i+"");
Thread.sleep(1);
}
} catch (InterruptedException e) {
System.out.println("the thread is interrupted");//可以在这里做资源释放,日志记录等
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" end");
}
});
t1.start();
Thread.sleep(100);
t1.interrupt();
执行结果:
65
66
67
68
the thread is interrupted
java.lang.InterruptedException: sleep interrupted
Thread-0 end
at java.lang.Thread.sleep(Native Method)
at com.wk.aqi.act.Test$1.run(Test.java:23)
at java.lang.Thread.run(Thread.java:745)
isInterrupted()
判断线程是否中断,在执行上面的interrupt方法后,会return true。
setPriority(int newPriority)和getPriority()
设置线程的优先级和获取线程的优先级,cpu分配的资源给侧重给priority高的线程。
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
long t = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+" start");
for(int i=0;i<1000;i++){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+" t1 end "+(System.currentTimeMillis()-t));
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
long t = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+" start");
for(int i=0;i<1000;i++){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+" t2 end "+(System.currentTimeMillis()-t));
}
});
t1.setPriority(10);
t2.setPriority(1);
t2.start();
t1.start();
执行结果:
Thread-0 start
Thread-1 start
Thread-0 t1 end 1357
Thread-1 t2 end 1371
在优先级一样的情况下,t1和t2是几乎同时完成的,在优先级不一样的情况,有明显的差别。
getName()
比较简单,获取线程的名称。
join()和join(long millis)
jion方法的作用是等待线程执行完成,join(long millis)可以设置最长等待时间。比如主线程需要等待子线程完成,获取子线程的结果后才能继续往下执行,这时候就可以使用join方法
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
long t = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+" start");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" t1 end "+(System.currentTimeMillis()-t));
}
});
t1.start();
t1.join();
System.out.println("等待t1执行完,再执行");
执行结果:
Thread-0 start
Thread-0 t1 end 1001
等待t1执行完,再执行
来源:https://segmentfault.com/a/1190000012213171
猜你喜欢
- 一、基本特点1. 开始时是乐观锁, 如果锁冲突频繁, 就转换为悲观锁.2. 开始是轻量级锁实现, 如果锁被持有的时间较长, 就转换成重量级锁
- 在linux主机部署Eureka高可用方案的时候,发现注册到服务中心的服务IP是随机的,由于主机的网卡是多个,随机的IP并不是自己想要的,上
- 今天来分析Configuration初始化的最后一部分mapper的加载。加载方法mapperElementXMLConfigBuilder
- 编码&解码 通过下图我们可以了解在javaWeb中有哪些地方有转码:用户想服务器发送一个HTTP请求,需要编码的地方有ur
- 本文实例讲述了Java文件操作工具类fileUtil。分享给大家供大家参考,具体如下:package com.gcloud.common;i
- Android 自动获取验证码的两种方式分别是BroadcastReceiver及ContentObserver,两种方式都需要进行注册、取
- 本文实例为大家分享了安装和配置maven环境的具体步骤,供大家参考,具体内容如下下载maven:1.进入官网下载:http://maven.
- 一、注解是什么Java 注解用于为 Java 代码提供元数据,看完这句话也许你还是一脸懵逼,用人话说就是注解不直接影响你的代码执行,仅提供信
- Unity IPostBuildPlayerScriptDLLsUnity IPostBuildPlayerScriptDLLs是Unity
- 配置步骤:1.导入Spring整合Junit的jar(坐标):<dependency> <gr
- 一、摘要这篇文章将介绍Spring整合Mybatis 如何完成SqlSessionFactory的动态切换的。并且会简单的介绍下MyBati
- 1. 数据构造索引2个文档到 hotel 索引中:PUT /hotel/_doc/1{ "title": &
- 添加记录后获取主键ID,这是一个很常见的需求,特别是在一次前端调用中需要插入多个表的场景。除了添加单条记录时获取主键值,有时候可能需要获取批
- 目录Java反射超详解1.反射基础1.1Class类1.2类加载2.反射的使用2.1Class对象的获取 2.2Construct
- 本文实例为大家分享了java生成验证码图片的具体代码,供大家参考,具体内容如下示例一:import org.apache.commons.c
- foreach 循环 list(map)直接上代码:整体需求就是1.分页对象里面有map map里面又有数组对象2.分页对象里面有list
- 1、什么是 ThreadLocal:ThreadLocal,即线程本地变量,如果你创建了一个变量,那么访问这个变量的每个线程都会有这个变量的
- 前言本文章接上一篇文章继续谈一谈condition的一些用法。案例上一篇文章我提的一个需求时导入jedis坐标后才能加载该Bean,否则不加
- spring boot 使用POI读取Excel文件Excel文件目录Excel模板文件存了resourse目录下,如下图:<depe
- C#中,有些类型是可以隐式转换的,我整理了这些可以隐式转换的类型,供大家参考 static