Java线程的启动和停止(一)
如何构造线程
在运行线程之前需要先构造线程对象,线程对象的构造需要指定线程所需要的属性,比如:所属线程组、线程优先级、是否为Daemon线程等信息。下面我们看一下,java.lang.Thread中对线程初始化的方法:
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals) {
if (name == null) {
throw new NullPointerException("name cannot be null");
}
//线程名称
this.name = name;
//当前线程就是该线程的父线程
Thread parent = currentThread();
SecurityManager security = System.getSecurityManager();
if (g == null) {
/* Determine if it's an applet or not */
/* If there is a security manager, ask the security manager
what to do. */
if (security != null) {
g = security.getThreadGroup();
}
/* If the security doesn't have a strong opinion of the matter
use the parent thread group. */
if (g == null) {
g = parent.getThreadGroup();
}
}
/* checkAccess regardless of whether or not threadgroup is
explicitly passed in. */
g.checkAccess();
/*
* 是否有访问权限
*/
if (security != null) {
if (isCCLOverridden(getClass())) {
security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
g.addUnstarted();
//线程组
this.group = g;
//使用父线程的daemon、priority属性
this.daemon = parent.isDaemon();
this.priority = parent.getPriority();
if (security == null || isCCLOverridden(parent.getClass()))
this.contextClassLoader = parent.getContextClassLoader();
else
this.contextClassLoader = parent.contextClassLoader;
this.inheritedAccessControlContext =
acc != null ? acc : AccessController.getContext();
this.target = target;
setPriority(priority);
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
/* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize;
/* 分配一个线程ID */
tid = nextThreadID();
}
一个 新 构造 的 线程 对象 是 由其 parent 线程 来 进行 空间 分配 的, 而 child 线程 继承 了 parent 是否 为 Daemon、 优先级 和 加载 资源 的 contextClassLoader 以及 可继承 的 ThreadLocal, 同时 还会 分配 一个 唯一 的 ID 来 标识 这个 child 线程。 至此, 一个 能够 运行 的 线程 对象 就 初始化 好了, 在 堆 内存 中 等待 着 运行。
我们构造一个Thread thread=new Thread(),打上断点,可以看到thread对象的属性如下:
如何使用线程
实现多线程编程的方式主要有两种:一种是继承Thread类,一种是实现Runnable接口,使用继承Thread类最大的局限性是不支持多继承,由于java单继承的特性,为了突破单继承的限制,于是就有了另一个实现方式,就是实现Runnable接口。使用这两种方式创建的线程工作性质是一样的,没有本质的区别。
继承Thread类
public class MyThread extends Thread {
@Override
public void run() {
super.run();
System.out.println("我是自定义线程MyThread");
}
}
实现Runnable接口
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("我是Runnable");
}
}
如何启动线程
线程对象初始化完成后,调用线程的start()方法就可以启动线程了,start()方法是告诉Java虚拟机,如果线程规划期空闲,应该立即启动调用了start()方法的线程。
同一个线程不能多次 调用 start() 方法, 否则会出现异常 Exception in thread” main” java. lang. IllegalThreadStateException。
线程的start()方法,会新启动一个线程,而线程run()方法则是同步等待当前线程调用。
如何停止线程
如何判断线程是否停止
在介绍如何停止线程的知识点前, 先看一下如何判断线程是否停止的状态。 Thread.java类中提供了两个很重要的方法:
1) this.interrupted(): 判断当前线程是否已经中断
2) this.isInterrupted(): 判断线程是否已经中断
那么这两种方法的区别是什么呢? 先来看看 this.interrupted()方法: 判断当前线程是否已经中断,当前线程是指运行 this. interrupted()方法 的 线程。
public static void main(String[] args) {
Thread.currentThread().interrupt();
String threadName = Thread.currentThread().getName();
System.out.println(threadName + " 当前线程是否已停止:=" + Thread.interrupted());
System.out.println(threadName + " 当前线程是否已停止:=" + Thread.interrupted());
}
main 当前线程是否已停止:=true
main 当前线程是否已停止:=false
从执行结果可知 interrupt()方法确实停止了线程,但是第二个判断结果为什么是false呢,通过查看官方文档当解释得知。interrupted() 具有清除状态的功能,所以第二个判断结果为false
下面我们接着查看 isInterrupted()方法:
public static void main(String[] args) {
Thread.currentThread().interrupt();
String threadName = Thread.currentThread().getName();
System.out.println(threadName + " 当前线程是否已停止:=" + Thread.currentThread().isInterrupted());
System.out.println(threadName + " 当前线程是否已停止:=" + Thread.currentThread().isInterrupted());
}
main 当前线程是否已停止:=true
main 当前线程是否已停止:=true
输出的结果都为true,isInterrupted()并未清除状态标志,最后我们得出如下结论:
1) this.interrupted(): 判断线程终止的状态, 执行后具有将状态标志置为false的功能
2) this.isInterrupted():判断线程终止的状态,不具有清除状态标志的功能
try..catch与this.interrupt方法终止线程
public class MyThread extends Thread {
@Override
public void run() {
super.run();
for (int i = 0; i < 5000; i++) {
if (interrupted()) {
System.out.println(Thread.currentThread().getName() + " 我被停止了,退出循环");
break;
}
System.out.println(" i=" + (i + 1));
}
}
}
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.setName("Thread-interrupt-0");
thread.start();
try {
Thread.sleep(1);
thread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" 结束!");
}
输出结果:
.....
i=32
i=33
i=34
i=35
i=36
i=37
i=38
i=39
i=40
i=41
结束!
Thread-interrupt-0 我被停止了,退出循环
过期的 suspend()、 resume() 和 stop()方法终止线程
suspend()在调用后线程不会释放已经占有的资源,二是占有着资源进入睡眠状态,这样容易引发死锁问题。同样的stop()方法在终止一个线程时不会保证线程的资源正常释放,通常线程没有机会去释放资源,因此会导致程序工作状态的不确定性。
正是因为 suspend()、 resume() 和 stop() 方法 带来的副作用, 这些方法才被标志位不建议使用的过期方法, 而暂停和恢复可以使用 等待/ 通知机制 来替代。
Java线程的启动和停止(一)的更多相关文章
- Java线程的启动与中止
一.线程与进程的关系 关于进程与线程,百度百科上是这样描述的: 进程(Process) 是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础. 在当 ...
- 面试官:Java 线程如何启动的?
摘要:Java 的线程创建和启动非常简单,但如果问一个线程是怎么启动起来的往往并不清楚,甚至不知道为什么启动时是调用start(),而不是调用run()方法呢? 本文分享自华为云社区<Threa ...
- Java线程状态、线程start方法源码、多线程、Java线程池、如何停止一个线程
下面将依次介绍: 1. 线程状态.Java线程状态和线程池状态 2. start方法源码 3. 什么是线程池? 4. 线程池的工作原理和使用线程池的好处 5. ThreadPoolExecutor中的 ...
- java -jar shell 启动、停止
启用 vi start.sh #!/bin/sh # ################################################################## # Powe ...
- java线层的启动与停止
class Do8 { public static void main(String[] args) { Resource r =new Resource(); Input in =new Input ...
- JAVA线程初体验
线程的创建 线程的启动和停止 /** * 演员类 继承Thread类 * @author Administrator * */ public class Actor extends Thread { ...
- Java线程池的那些事
熟悉java多线程的朋友一定十分了解java的线程池,jdk中的核心实现类为java.util.concurrent.ThreadPoolExecutor.大家可能了解到它的原理,甚至看过它的源码:但 ...
- 基于 JVMTI 实现 Java 线程的监控(转)
随着多核 CPU 的日益普及,越来越多的 Java 应用程序使用多线程并行计算来充分发挥整个系统的性能.多线程的使用也给应用程序开发人员带来了巨大的挑战,不正确地使用多线程可能造成线程死锁或资源竞争, ...
- 一个ScheduledExecutorService启动的Java线程无故挂掉引发的思考
2018年12月12日18:44:53 一个ScheduledExecutorService启动的Java线程无故挂掉引发的思考 案件现场 不久前,在开发改造公司一个端到端监控日志系统的时候,出现了一 ...
随机推荐
- MySQL 官方样板数据库sakila
Sakila示例数据库最初由MySQL AB文档团队的前成员Mike Hillyer开发,旨在提供可用于书籍,教程,文章,样本等示例的标准模式. Sakila示例数据库还用于突出MySQL的最新功能, ...
- HttpContext is null
HttpContext context1 = System.Web.HttpContext.Current; HttpContext context2 = System.Runtime.Remotin ...
- Entity的约束
在DBContext的OnModelCreating()方法中调用上面的那个类 1.Infrastruture的Database文件夹建立Entityconfiguretions的文件夹 2.MyCo ...
- python+django学习二
所有模型类型的准备和迁移 在setting.py中添加:AUTH_USER_MODEL = 'users.UserProfile' 继承用户模板 确保子项目的url现在都是空的, 在pycharm的f ...
- sonarqube执行命令遇上的小问题
在安装好sonarqube,本地或是服务器上都是可疑正常运行的情况下. 这一次我重新上传,修改配置SonarQube.Analysis.xml,sonar.host.url的值已经改为服务器上的,执行 ...
- 网络编程之NIO
传统的BIO(Blocking IO)的缺点: 1.基于阻塞式IO建立起来的,导致服务端一直阻塞等待着客户端发起请求,如果客户端不发起,服务端的的业务线程会一直存. 2.弹性伸缩能力差,线程数和客户端 ...
- Mac命令行提示
之前看到一个大神的终端主题好炫,所以自己也想弄一个.看了很多中文的教程都不是很靠谱,效果并没有实现.不能说人家的不对,只能说自己水平有限.后来直接去看 github 上的官方教程,因为是官方嘛~所以肯 ...
- 转载一篇让你全面了解什么是.NET。
转载于:https://www.52abp.com/BlogDetails/10009 阅读文本大概需要 8 分钟. 持续进化的 .NET 这张图即是一个学习的路线图同样他也是 .NET 平台的进化图 ...
- css 之内容溢出滚动,隐藏滚动条(解决火狐浏览隐藏不了滚动条问题)
解决火狐浏览隐藏不了滚动条问题 1.里层容器的width多17px,外层容器溢出隐藏,能兼容各个浏览器 .outContainer { width:350px; height:300px; overf ...
- python中的网络通信,socket、select、selectors、socketserver
楔子 网络通信用于获取一个算法在本地运行所需的数据,还可以共享信息实现分布式处理,另外可以用来管理云服务. python的标准库提供了一些模块来创建网络服务以及访问现有服务ipaddress模块提供了 ...