版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/baidu_37378518/article/details/85122409
线程的启动及常用方法
对于线程的启动来说,首先涉及到的就是run()和start()这两个方法。一种方法是继承Thread类,覆盖run方法;一种是实现Runnable接口。
因为开启线程的start方法只在Thread类中存在,所以两种方法都需要借助Thread类中的start()来开启线程。
//在Runable接口中只有一个run方法
public interface Runnable {
public abstract void run();
}
//Thread类实现了Runnable
public class Thread implements Runnable{
public synchronized void start() {
//如果多次调用start(),会抛出IllegalThreadStateException异常
if (threadStatus != 0)
throw new IllegalThreadStateException();
//...
}
//由此构造方法可知,还可传入一个Thread对象,
//将一个Thread对象的run()交给其他线程进行调用
public Thread(Runnable target) {
//...
}
}
/**
* Tests if this thread is alive. A thread is alive if it has
* been started and has not yet died.
* 线程还未执行完毕
*/
public final native boolean isAlive();
/**
* Returns a reference to the currently executing thread object.
*/
public static native Thread currentThread();
//sleep方法
public static void sleep(long millis, int nanos)
throws InterruptedException {
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
millis++;
}
sleep(millis);
}
public static native void sleep(long millis) throws InterruptedException;
//getId()
private long tid;
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals) {
//...
/* Set thread ID */
tid = nextThreadID();
}
/* For generating thread ID */
private static long threadSeqNumber;
private static synchronized long nextThreadID() { return ++threadSeqNumber; }
public long getId() { return tid; }
// A hint to the scheduler that the current thread is willing to yield
// its current use of a processor. The scheduler is free to ignore this
// hint.
public static native void yield();
如何暂停线程
@Deprecated
public final void suspend() {
//Determines if the currently running thread has permission to modify this thread.
checkAccess();
suspend0();
}
private native void suspend0();
@Deprecated
public final void resume() {
checkAccess();
resume0();
}
private native void resume0();
缺点:
- 如果使用不当,易造成公共的同步对象的独占,使得其它线程无法访问公共同步对象(线程进入synchronized代码块中被suspend时,不释放锁)
- 容易导致数据不同步(同步块中,属性值修改到一半被suspend,然后有其他线程读取)
如何停止线程
停止线程:在线程处理完任务之前停掉正在做的操作
停止线程的3中方法:
- run()完成后线程终止
- 使用stop()强行终止线程,可能产生不可预料的结果,该方法已被废弃
- stop()会在run()中的任何地方抛出ThreadDeath异常来停止线程
- 这种方式,可能导致持有的锁被突然释放,导致数据的一致性被破坏
- 可能使一些请理性的工作得不到完成
- interrupt()中断线程
- 该方法仅仅是在当前线程中打了一个interrupt的标志
interrupted()与isInterrupted()
//检测当前线程是否是已经中断状态,执行后具有将状态标记清楚为false的功能
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
//测试Thread对象是否已经是中断状态,但不清除状态标志
public boolean isInterrupted() {
return isInterrupted(false);
}
private native boolean isInterrupted(boolean ClearInterrupted);
能停止线程的方法
(interrupt标志的作用:打上标志之后,线程会继续运行,一旦线程进入sleep状态,就会抛异常,停止线程)
- 在使用interrupt()之后,检测中断状态,抛出异常来停止线程
- 在线程sleep状态下,调用interrupt(),会抛出异常,并清除停止状态值,使之变成false
- 先调用interrupt(),然后再让线程进入sleep状态,也会抛出异常
- interrupt()与return结合也能停止线程,通过检测线程中断状态
扫描二维码关注公众号,回复:
4816455 查看本文章
线程的优先级
CPU优先执行优先级较高的线程对象中的任务
public final static int MIN_PRIORITY = 1;
public final static int NORM_PRIORITY = 5;
public final static int MAX_PRIORITY = 10;
public final void setPriority(int newPriority) {
ThreadGroup g;
checkAccess();
if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
throw new IllegalArgumentException();
}
if((g = getThreadGroup()) != null) {
if (newPriority > g.getMaxPriority()) {
newPriority = g.getMaxPriority();
}
setPriority0(priority = newPriority);
}
}
private native void setPriority0(int newPriority);
优先级特性:
- 继承性:A线程启动B线程,则B线程的优先级与A相同
- 规则性:优先级高的大部分先执行完
- 随机性:优先级高的不一定每次都先执行完
守护线程
当进程中不存在非守护线程时,守护线程自动销毁(垃圾回收线程)
/* Whether or not the thread is a daemon thread. */
private boolean daemon = false;
public final void setDaemon(boolean on) {
checkAccess();
if (isAlive()) {
throw new IllegalThreadStateException();
}
daemon = on;
}