简介JAVA中多线程的开发中少不了使用Thread,我们在使用Thread中提供的API过程中,应该注意些什么规则呢?
一起来看一看吧 。
start一个ThreadThread中有两个方法,一个是start方法,一个是run方法,两个都可以调用,那么两个有什么区别呢?
先看一下start方法:
public synchronized void start() {if (threadStatus != 0)throw new IllegalThreadStateException();group.add(this);boolean started = false;try {start0();started = true;} finally {try {if (!started) {group.threadStartFailed(this);}} catch (Throwable ignore) {}}}private native void start0();
start()是一个synchronized的方法,通过它会去调用native的start0方法,而最终将会调用Thread的run()方法 。
我们知道,创建一个Thread有两种方式,一种是传入一个Runnable,一个是继承Thread,并重写run()方法 。
如果我们直接调用Thread的run()方法会发生什么事情呢?
先看一下run方法的定义:
public void run() {if (target != null) {target.run();}}
默认情况下, 这个target就是一个Runnable对象,如果Thread是通过Runnable来构建的话,调用Thread.run()会在当前线程中运行run方法中的内容 。
如果Thread是以其形式构建,并且没有重新run()方法,那么直接调用Thread.run()将什么都不会做 。
public void wrongStart(){Runnable runnable= ()-> System.out.println("in thread running!");Thread thread= new Thread(runnable);thread.run();}public void correctStart(){Runnable runnable= ()-> System.out.println("in thread running!");Thread thread= new Thread(runnable);thread.start();}
所以,上面两种调用方式,只有第二种是正确的 。
不要使用ThreadGroup【java安全编码指南之:Thread API调用规则】Thread中有个字段类型是java.lang.ThreadGroup,这个主要是用来给Thread进行分组,我们看下Thread的这个构造函数:
public Thread(ThreadGroup group, Runnable target) {this(group, target, "Thread-" + nextThreadNum(), 0);}
上面的构造函数可以在传入runnable的同时传递一个ThreadGroup对Thread进行分组 。
如果没有指定ThreadGroup,那么将会为其分配一个默认的default group 。
ThreadGroup是做什么的呢?ThreadGroup是java 1.0引入的方法,主要是一次性的对一组thread进行操作 。我们可以调用ThreadGroup.interrupt()来一次性的对整个Group的Thread进行interrupts操作 。
虽然ThreadGroup提供了很多有用的方法,但是其中很多方法都被废弃了,比如:allowThreadSuspension(), resume(), stop(), 和 suspend(),并且ThreadGroup中还有很多方法是非线程安全的:
- ThreadGroup.activeCount()
- ThreadGroup.enumerate()
ThreadGroup本身有一个 stop() 方法用来停止所有的线程,但是stop是不安全的,已经被废弃了 。
那么我们该怎么去安全的停止很多个线程呢?
使用executor.shutdown()就可以了 。
不要使用stop()方法刚刚讲了ThreadGroup中不要调用stop()方法,因为stop是不安全的 。
调用stop方法会立马释放线程持有的所有的锁,并且会抛出ThreadDeath异常 。
因为会释放所有的锁,所以可能会造成受这些锁保护的对象的状态发生不一致的情况 。
替代的方法有两种,一种是使用volatile flag变量,来控制线程的循环执行:
private volatile boolean done = false;public void shutDown(){this.done= true;}public void stopWithFlag(){Runnable runnable= ()->{while(!done){System.out.println("in Runnable");}};Thread thread= new Thread(runnable);thread.start();shutDown();}
另外一种方法就是调用interrupt(), 这里我们要注意interrupt()的使用要点:- 如果当前线程实例在调用Object类的wait(),wait(long)或wait(long,int)方法或join(),join(long),join(long,int)方法,或者在该实例中调用了Thread.sleep(long)或Thread.sleep(long,int)方法,并且正在阻塞状态中时,则其中断状态将被清除,并将收到InterruptedException 。
- 如果此线程在InterruptibleChannel上的I/O操作中处于被阻塞状态,则该channel将被关闭,该线程的中断状态将被设置为true,并且该线程将收到java.nio.channels.ClosedByInterruptException异常 。
- 如果此线程在java.nio.channels.Selector中处于被被阻塞状态,则将设置该线程的中断状态为true,并且它将立即从select操作中返回 。
推荐阅读
- 烘鞋器烘一晚上安全吗 烘鞋器会不会着火
- 登山安全注意事项有哪些呢
- 安卓|Android被爆重要安全漏洞:根源竟来自苹果
- 提升网站安全性-隐藏nginx信息
- Javascript中reduce的8种用例
- 散粉里边有滑石粉 花西子散粉成分安全吗,含滑石粉吗
- 如何高效利用Java UI组件库,开发现代化图形用户界面
- 服务器安全需要注意的几个方面
- 一文读懂 Java操作Elasticsearch
- 五菱|3999元 五菱造了一把椅子:还带腿托和安全带