目录
3.1 CurrentThread(): 这是一个 静态的方法---- statuc Thread
3.2 Thread.getId() ----------- long
3.3 sleep(long millis) : - -------- static void
3.4 setName(String name) 和 getName()
3.8 setPriority(int newPriority)
1. 构造方法
Thread()
分配一个新的
Thread
对象。Thread(Runnable target)
分配一个新的
Thread
对象。Thread(Runnable target, String name)
分配一个新的
Thread
对象。Thread(String name)
分配一个新的
Thread
对象。Thread(ThreadGroup group, Runnable target)
分配一个新的
Thread
对象。Thread(ThreadGroup group, Runnable target, String name)
分配一个新的
Thread
对象,使其具有target
作为其运行对象,具有指定的name
作为其名称,属于group
引用的线程组。Thread(ThreadGroup group, Runnable target, String name, long stackSize)
分配一个新的
Thread
对象,以便它具有target
作为其运行对象,将指定的name
正如其名,以及属于该线程组由称作group
,并具有指定的 堆栈大小 。Thread(ThreadGroup group, String name)
分配一个新的
Thread
对象。
2 .所有方法
static int
activeCount()
返回当前线程的thread group及其子组中活动线程数的估计。
void
checkAccess()
确定当前正在运行的线程是否有权限修改此线程。
protected Object
clone()
将CloneNotSupportedException作为线程抛出无法有意义地克隆。
int
countStackFrames()
已弃用此呼叫的定义取决于
suspend()
,它已被弃用。 此外,此呼叫的结果从未明确。static Thread
currentThread()
返回对当前正在执行的线程对象的引用。
void
destroy()
已弃用这种方法最初是为了销毁这个线程而没有任何清理。 它所持有的任何监视器都将保持锁定。 但是,该方法从未实现。 如果要实施,那么它将是
suspend()
的方式是僵死的 。 如果目标线程在销毁时保护关键系统资源的锁,则无法再次访问该资源。 如果另一个线程曾尝试锁定此资源,将导致死锁。 这种僵局通常表现为“冻结”过程。 有关详细信息,请参阅Why are Thread.stop, Thread.suspend and Thread.resume Deprecated? 。static void
dumpStack()
将当前线程的堆栈跟踪打印到标准错误流。
static int
enumerate(Thread[] tarray)
将当前线程的线程组及其子组中的每个活动线程复制到指定的数组中。
static Map<Thread,StackTraceElement[]>
getAllStackTraces()
返回所有活动线程的堆栈跟踪图。
ClassLoader
getContextClassLoader()
返回此Thread的上下文ClassLoader。
static Thread.UncaughtExceptionHandler
getDefaultUncaughtExceptionHandler()
返回当线程由于未捕获异常突然终止而调用的默认处理程序。
long
getId()
返回此线程的标识符。
String
getName()
返回此线程的名称。
int
getPriority()
返回此线程的优先级。
StackTraceElement[]
getStackTrace()
返回表示此线程的堆栈转储的堆栈跟踪元素数组。
Thread.State
getState()
返回此线程的状态。
ThreadGroup
getThreadGroup()
返回此线程所属的线程组。
Thread.UncaughtExceptionHandler
getUncaughtExceptionHandler()
返回由于未捕获的异常,此线程突然终止时调用的处理程序。
static boolean
holdsLock(Object obj)
返回 true当且仅当当前线程在指定的对象上保持监视器锁。
void
interrupt()
中断这个线程。
static boolean
interrupted()
测试当前线程是否中断。
boolean
isAlive()
测试这个线程是否活着。
boolean
isDaemon()
测试这个线程是否是守护线程。
boolean
isInterrupted()
测试这个线程是否被中断。
void
join()
等待这个线程死亡。
void
join(long millis)
等待这个线程死亡最多
millis
毫秒。void
join(long millis, int nanos)
等待最多
millis
毫秒加上nanos
纳秒这个线程死亡。void
resume()
已弃用该方法仅用于与
suspend()
一起使用,因为它是死锁倾向的,因此已被弃用。 有关详细信息,请参阅Why are Thread.stop, Thread.suspend and Thread.resume Deprecated? 。void
run()
如果这个线程使用单独的
Runnable
运行对象构造,则调用该Runnable
对象的run
方法; 否则,此方法不执行任何操作并返回。void
setContextClassLoader(ClassLoader cl)
设置此线程的上下文ClassLoader。
void
setDaemon(boolean on)
将此线程标记为 daemon线程或用户线程。
static void
setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
设置当线程由于未捕获的异常突然终止而调用的默认处理程序,并且没有为该线程定义其他处理程序。
void
setName(String name)
将此线程的名称更改为等于参数
name
。void
setPriority(int newPriority)
更改此线程的优先级。
void
setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
设置当该线程由于未捕获的异常而突然终止时调用的处理程序。
static void
sleep(long millis)
使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性。
static void
sleep(long millis, int nanos)
导致正在执行的线程以指定的毫秒数加上指定的纳秒数来暂停(临时停止执行),这取决于系统定时器和调度器的精度和准确性。
void
start()
导致此线程开始执行; Java虚拟机调用此线程的
run
方法。void
stop()
已弃用这种方法本质上是不安全的。 使用Thread.stop停止线程可以解锁所有已锁定的监视器(由于未
ThreadDeath
ThreadDeath异常在堆栈中ThreadDeath
的自然结果)。 如果先前受这些监视器保护的任何对象处于不一致的状态,则损坏的对象将变得对其他线程可见,可能导致任意行为。stop
许多用途应该被替换为只是修改一些变量以指示目标线程应该停止运行的代码。 目标线程应该定期检查此变量,如果变量表示要停止运行,则以有序方式从其运行方法返回。 如果目标线程长时间等待(例如,在interrupt
变量上),则应该使用interrupt
方法来中断等待。 有关详细信息,请参阅Why are Thread.stop, Thread.suspend and Thread.resume Deprecated? 。void
stop(Throwable obj)
已弃用该方法最初设计为强制线程停止并抛出一个给定的
Throwable
作为例外。 它本质上是不安全的(有关详细信息,请参阅stop()
),此外还可用于生成目标线程未准备处理的异常。 有关详细信息,请参阅Why are Thread.stop, Thread.suspend and Thread.resume Deprecated? 。void
suspend()
已弃用这种方法已被弃用,因为它本身就是死锁的。 如果目标线程在挂起时保护关键系统资源的监视器上的锁定,则在目标线程恢复之前,线程不能访问该资源。 如果要恢复目标线程的线程在调用
resume
之前尝试锁定此监视器,resume
导致死锁。 这种僵局通常表现为“冻结”过程。 有关详细信息,请参阅Why are Thread.stop, Thread.suspend and Thread.resume Deprecated? 。String
toString()
返回此线程的字符串表示,包括线程的名称,优先级和线程组。
static void
yield()
对调度程序的一个暗示,即当前线程愿意产生当前使用的处理器。
以上摘自文档
3. 常用方法和对应代码演示
3.1 CurrentThread(): 这是一个 静态的方法---- statuc Thread
- 返回当前正在执行线程对象的引用。
- 在JAVA中,任何一段代码都是执行在某一个线程当中,执行当前代码的线程就是当前线程。
- 同一段代码可以被不同执行,因此当前线程是相对的,Thread.currentThread() 方法返回的代码在实际运行的线程对象。
package stu.my.cdn.threadmethod;
public class SubThread1 extends Thread{
public SubThread1() {
System.out.println("构造方法打印当前线程名称:"+Thread.currentThread().getName());
}
@Override
public void run() {
System.out.println("run 方法打印当前线程的名称:"+Thread.currentThread().getName());
}
public static void main(String[] args) {
System.out.println("main 方法中打印当前线程:" + Thread.currentThread().getName());
SubThread1 subThread1 = new SubThread1();
subThread1.start(); //启动子线程
}
}
因为在main线程中构造了子线程的构造方法,所以构造方法在当前 main 线程执行。
3.2 Thread.getId() ----------- long
- 获得线程的唯一标识。
- 线程ID是创建此线程时生成的正数long号。
- 线程ID是唯一的,并且在其生命周期内保持不变。 当线程被终止时,该线程ID可以被重用。
package stu.my.cdn.threadmethod;
public class GetId extends Thread{
@Override
public void run() {
System.out.println("Thread name = " + Thread.currentThread().getName()
+ " id == " + this.getId());
}
public static void main(String[] args) {
System.out.println("Thread name = " + Thread.currentThread().getName()
+ " id == " + Thread.currentThread().getId());
// 子线程 id
for(int i = 1; i < 10; i++){
new GetId().start();
}
}
}
注意:
某个编号的线程运行结束后,该编号可能被后续创建的线程使用。
重启 JVM 后,同一个线程编号可能不一样。
3.3 sleep(long millis) : - -------- static void
- 使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性。
- 线程不会丢失任何显示器的所有权。
- 当前线程就是 Thread.currentThread() 返回的线程。
package stu.my.cdn.threadmethod.sleep;
public class Sleep extends Thread{
@Override
public void run() {
System.out.println("run_begin"+System.currentTimeMillis());
try {
sleep(500);
System.out.println("run_end" + System.currentTimeMillis());
} catch (InterruptedException e) {
// 在子线程的 run 方法中,如果有受检异常(编译时异常)需要处理,只有选择捕获异常,不能抛出异常
e.printStackTrace();
}
}
public static void main(String[] args) {
Sleep sleep = new Sleep();
System.out.println("main_begin---"+System.currentTimeMillis());
sleep.start(); // 开启新的线程
// sleep.run(); // 在main线程中调用实例的run() ,没有开启新的线程
System.out.println("main_end---"+System.currentTimeMillis());
}
}
因为子线程使用了sleep休眠了500ms,所以main线程先执行结束了程序。
实现计时器--使用sleep(1000)
package stu.my.cdn.threadmethod.sleep;
public class SimplerTimer {
public static void main(String[] args) {
int remaining = 60; // 从 60 秒开始计时
// 读取 main 方法参数
if(args.length == 1){
remaining = Integer.parseInt(args[0]);
}
while(true){
System.out.println("remaining:" + remaining );
remaining--;
if(remaining < 0 ){
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Done!!!");
}
}
3.4 setName(String name) 和 getName()
setName(String name)
- 将此线程的名称更改为等于参数
name
。 - 首先调用这个线程的
checkAccess
方法,没有参数。 这可能会导致投掷SecurityException
。
getName()
- 返回此线程的名称。
3.5 isAlive()
- 测试这个线程是否活着。
- 如果一个线程已经启动并且尚未死亡,那么线程是活着的。
package stu.my.cdn.threadmethod;
public class IsAlive extends Thread{
@Override
public void run() {
System.out.println("run");
}
public static void main(String[] args) {
IsAlive isAlive = new IsAlive();
System.out.println("begin==》" + isAlive.isAlive());
isAlive.start();
System.out.println("end == > " + isAlive.isAlive());
}
}
因为刚开始线程还未启动,所以线程处于为活动状态,所以返回 false。而当执行start方法,线程开始活动,则为true
3.6 start() ------------ void
- 导致此线程开始执行; Java虚拟机调用此线程的
run
方法。 - 结果是两个线程同时运行:当前线程(从调用返回到
start
方法)和另一个线程(执行其run
方法)。 - 不止一次启动线程是不合法的。 特别地,一旦线程完成执行就可能不会重新启动。
3.7 yield ()
- 对调度程序的一个暗示,即当前线程愿意产生当前使用的处理器。 调度程序可以自由地忽略这个提示。
- 产量是一种启发式尝试,以改善否则会过度利用CPU的线程之间的相对进度。 其使用应与详细的分析和基准相结合,以确保其具有预期的效果。
- 主要作用是放弃当前线程占有的 cpu 资源
package stu.my.cdn.threadmethod;
public class Yiled extends Thread {
@Override
public void run() {
long begin = System.currentTimeMillis();
long sum = 0;
for(int i = 1; i < 100000; i ++){
sum += i;
Thread.yield(); // 线程让步,放弃 CPU 资源
}
long end = System.currentTimeMillis();
System.out.println("run 用时:" + (end - begin));
}
public static void main(String[] args) {
Yiled yiled = new Yiled();
yiled.start();
long begin = System.currentTimeMillis();
long sum = 0;
for(int i = 1; i < 100000; i ++){
sum += i;
}
long end = System.currentTimeMillis();
System.out.println("main方法用时:" + (end - begin));
}
}
使用 yield() 方法,放弃了当前 CPU 占有资源。
3.8 setPriority(int newPriority)
- 设置线程的优先级
- java 线程的优先级取值范围是 1 ~ 10 ,如果超出这个范围会抛出异常
IllegalArgumentException
-
在操作系统中,优先级较高的线程获得 CPU 的资源越多
-
线程优先级本质上只是给线程调度器一个提示信息,以便于调度器决定先调度那些线程,注意不能保证优先级高的程序先运行。
-
JAVA 优先级设置不当,或者滥用,可能会导致某些线程永远无法得到运行,既产生了线程饥饿。
package stu.my.cdn.threadmethod;
public class SetPriority extends Thread{
@Override
public void run() {
long begin = System.currentTimeMillis();
int sum = 0 ;
for(int i = 0; i < 1000000000; i++){
sum += i;
}
long end = System.currentTimeMillis();
System.out.println("end- begin ==" + (end-begin));
}
public static void main(String[] args) {
SetPriority setPriority1 = new SetPriority();
setPriority1.setPriority(1); // 设置优先级,优先级越高,获得CPU 的资源越多
setPriority1.start();
SetPriority setPriority2 = new SetPriority();
setPriority2.setPriority(10); // 优先级高,执行的越快
setPriority2.start();
}
}
3.9 interrupt()
- 中断这个线程
- 注意调用 interrupt() 方法仅仅是在当前线程打一个停止标志,并不是真正的停止线程。
3.10 interrupted()
- 测试当前线程是否被中断。
- 该方法可以清除线程的中断状态 。
package stu.my.cdn.threadmethod;
public class Interrupt extends Thread {
@Override
public void run() {
for(int i = 1; i < 10; i++){
System.out.println("sub thread ---> "+ i);
if(this.isInterrupted()){
System.out.println("当前线程中断标志为 true ,我要退出了");
// break; 中断循环
return; // 结束当前线程的执行
}
}
}
public static void main(String[] args) {
Interrupt interrupt = new Interrupt();
interrupt.start(); // 开启线程
// 当前main线程打印
for (int i = 0; i < 10; i++){
System.out.println("main == >" + i);
}
// 中断子线程
interrupt.interrupt(); // 仅仅是给子线程标记
}
}
对应每次执行结果不一,因为 interrupted() 可以清除线程的终断状态。CPU 在对于这么点程序,来回调度速度太快。
3.11 setDaemon()
- JAVA 的线程分为用户线程和守护线程
- 守护线程是为其它线程提供服务的线程,如垃圾回收器(GC) 就是一个典型的守护线程。
- 守护线程不能单独运行,当 JVM 中没有了其它的用户线程,只有了守护线程的时候,守护线程就会自动销毁,JVM 退出。
package stu.my.cdn.threadmethod;
public class SetDaemon extends Thread {
@Override
public void run() {
while(true){
System.out.println("sub thread......");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 设置线程为守护线程
*/
public static void main(String[] args) {
SetDaemon setDaemon = new SetDaemon();
// 设置线程为守护线程
setDaemon.setDaemon(true); // 设置守护线程一定要在线程启动前
setDaemon.start();
for(int i = 1; i < 10; i++){
System.out.println("mian== "+ i);
}
// main 线程结束,守护线程 setDaemon 也就销毁了
}
}
🤔🤔🤔🤔
当用户线程完成之后,守护线程便自动终止。