1、start() 方法:使一个线程启动,并执行该线程对应的run()方法
说明:
> 线程只能启动一次,一旦线程启动了,再次启动会抛出java.lang.IllegalThreadStateException异常
package org.xyz.java.thread.demo02;
/**
* 线程的start方法讲解
* @author kevin.chen
*
*/
public class StartMethod {
public static void main(String[] args) {
// 使用匿名内部类,实现Runnable接口的方式来创建线程
Thread t = new Thread(new Runnable() {
@Override
public void run() {
for(int i = 0;i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "-run: "+ i);
}
}
});
// 在主线程中重新启动了一个新的线程,新的线程会执行run()方法(线程名为:Thread-0)
t.start();
// 主线程继续循环操作(线程名为:main)
for(int i = 0;i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "-main: "+ i);
}
// 再次调用一个启动过的线程,会抛出java.lang.IllegalThreadStateException异常
t.start();
}
}
运行结果:2个线程输出顺序是无序的,交错抢占cpu资源
main-main: 0
Thread-0-run: 0
main-main: 1
Thread-0-run: 1
main-main: 2
Thread-0-run: 2
main-main: 3
Thread-0-run: 3
main-main: 4
Thread-0-run: 4
main-main: 5
Thread-0-run: 5
main-main: 6
Thread-0-run: 6
main-main: 7
Thread-0-run: 7
Thread-0-run: 8
Thread-0-run: 9
main-main: 8
main-main: 9
Exception in thread "main" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Thread.java:708)
at org.xyz.java.thread.demo02.StartMethod.main(StartMethod.java:31)
> 启动线程是调用start(),而不是run()方法。
> 调用start()方法是在当前线程中重新启动一个新线程,之后会调用线程对象的run()方法;
> 而调用run()相当于调用对象的一个普通方法,不会启动线程,其执行的线程还是当前线程中执行
对比上面和下面的代码可以看出端倪:
package org.xyz.java.thread.demo02;
/**
* 线程的start方法讲解
* @author kevin.chen
*
*/
public class StartMethod {
public static void main(String[] args) {
// 使用匿名内部类,实现Runnable接口的方式来创建线程
Thread t = new Thread(new Runnable() {
@Override
public void run() {
for(int i = 0;i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "-run: "+ i);
}
}
});
// 在主线程中不会重新启动一个新的线程,只是调用类的普通方法,此时还是在主线程中(线程名为:main)
t.run();
// 而且,此时必须要等到上面的方法执行完之后再执行循环操作(线程名为:main)
for(int i = 0;i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "-main: "+ i);
}
}
}
运行结果:只有主线程一个线程,run方法是对象的一个普通方法,不会创建新的线程来执行,依旧在主线程中执行,run()方法执行后才会继续下面的代码
main-run方法: 0
main-run方法: 1
main-run方法: 2
main-run方法: 3
main-run方法: 4
main-run方法: 5
main-run方法: 6
main-run方法: 7
main-run方法: 8
main-run方法: 9
main-main方法: 0
main-main方法: 1
main-main方法: 2
main-main方法: 3
main-main方法: 4
main-main方法: 5
main-main方法: 6
main-main方法: 7
main-main方法: 8
main-main方法: 9
2、sleep() 方法:在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)
说明:
> 如果sleep方法在同步方法或同步代码块中调用,那么该线程在睡眠的过程中是不会释放同步锁的
> 线程的状态由之前的运行状态转换为超时等待状态,睡眠时间到后,线程状态由超时等待转换为可运行状态,重新抢占cpu的资源。
package org.xyz.java.thread.demo02;
/**
* 线程的sleep方法讲解
* 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)
* @author kevin.chen
*
*/
public class SleepMethod {
public static void main(String[] args) {
sleepTest();
}
public static void sleepTest() {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
for(int i = 0; i< 10; i++) {
try {
// 调用sleep方法,让线程休眠100毫秒
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ": " + i);
}
}
});
t.start();
}
}
3、join() 方法:将一个线程加入到另一个线程之前进行执行,直到加入的线程死亡。
说明:该方法有三个实现
> join() 无参的情况是加入的线程先执行完(cpu优先使用权)后再执行被加入的线程程序代码
> join(long millis) 该线程在加入指定的<毫秒>数之后和被加入的线程同时抢占cpu资源
> join(long millis,int nanos) 该线程在加入指定的<毫秒+纳秒>数之后和被加入的线程同时抢占cpu资源
> 不调 join 的情况
package org.xyz.java.thread.demo02;
/**
* 线程的join方法讲解
* 在一个线程中调用另一个线程的join方法,当前线程释放cpu使用权会挂起,join进来的线程先执行,执行完之后,被join的线程再继续执行。
* @author kevin.chen
*
*/
public class JoinMethod {
public static void main(String[] args) {
for(int i = 0; i < 10; i++) {
// 当主线程执行2次的时候,将另外一个新的线程join进来
if( i == 2) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
for(int i = 10; i < 20; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
}
}
});
t.start();
}
System.out.println(Thread.currentThread().getName() + ": " + i);
}
}
}
> 运行结果:
main: 0
main: 1
main: 2
main: 3
main: 4
main: 5
Thread-0: 10
main: 6
Thread-0: 11
Thread-0: 12
Thread-0: 13
Thread-0: 14
Thread-0: 15
main: 7
Thread-0: 16
main: 8
Thread-0: 17
main: 9
Thread-0: 18
Thread-0: 19
> 调用 join 的情况:
package org.xyz.java.thread.demo02;
/**
* 线程的join方法讲解
* 在一个线程中调用另一个线程的join方法,当前线程释放cpu使用权会挂起,join进来的线程先执行,执行完之后,被join的线程再继续执行。
* @author kevin.chen
*
*/
public class JoinMethod {
public static void main(String[] args) {
for(int i = 0; i < 10; i++) {
// 当主线程执行2次的时候,将另外一个新的线程join进来
if( i == 2) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
for(int i = 10; i < 20; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
}
}
});
t.start();
try {
// 线程的join()方法是会让被join的线程进入到阻塞状态,只有join的线程执行完毕之后才会继续执行下去
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + ": " + i);
}
}
}
> 运行结果:
main: 0
main: 1
Thread-0: 10
Thread-0: 11
Thread-0: 12
Thread-0: 13
Thread-0: 14
Thread-0: 15
Thread-0: 16
Thread-0: 17
Thread-0: 18
Thread-0: 19
main: 2
main: 3
main: 4
main: 5
main: 6
main: 7
main: 8
main: 9
4、yield() 方法:释放当前线程的cpu使用权
说明:
>线程释放cpu的使用权,不代表线程不再执行,释放cpu使用权的瞬间可能有抢占了cpu的使用权
package org.xyz.java.thread.demo02;
/**
* 线程的yield方法讲解
* 在一个线程中调用yield方法,当前线程会释放cpu使用权,线程状态从运行态转换为可运行态,和其他线程抢占cpu的使用权
* @author kevin.chen
*
*/
public class YieldMethod {
public static void main(String[] args) {
// 子线程
Thread t = new Thread(new Runnable() {
@Override
public void run() {
for(int i = 10; i < 20; i++) {
if(i > 15) {
// 让当前线程释放cpu的使用权
Thread.yield();
}
System.out.println(Thread.currentThread().getName() + ": " + i);
}
}
});
t.start();
// 主线程
for(int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
}
}
}
5、setPriority() 方法:设置线程的优先级
说明:
> 线程的优先级有1~10个等级值可供设置,1为优先级最低,10为优先级最高,默认不设置线程的优先级为5,如果父类线程设置了优先级,而子线程没有设置,那么子线程会继承父线程的优先级
> 优先级高的线程对抢占cpu的概率要大于优先级低的线程,但并不代表优先级高的线程一定先于优先级低的线程执行。
package org.xyz.java.thread.demo02;
/**
* 线程的setPriority方法、getPriority方法讲解
* 给一个线程设置优先级,优先级的值取值范围为1~10,取值越大,线程优先级越高,线程默认值为5
* @author kevin.chen
*
*/
public class PriorityMethod {
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for(int i=0; i< 10; i++) {
System.out.println(Thread.currentThread().getName() + "的优先级为: " + Thread.currentThread().getPriority());
}
}});
t1.setName("线程<1>");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
for(int i=0; i< 10; i++) {
System.out.println(Thread.currentThread().getName() + "的优先级为: " + Thread.currentThread().getPriority());
}
}});
t2.setName("线程[2]");
t2.setPriority(Thread.MAX_PRIORITY); // 最大优先级
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
for(int i=0; i< 10; i++) {
System.out.println(Thread.currentThread().getName() + "的优先级为: " + Thread.currentThread().getPriority());
}
}});
t3.setName("线程(3)");
t3.setPriority(Thread.MIN_PRIORITY);// 最小优先级
t1.start();
t2.start();
t3.start();
}
}
运行结果:优先级越高,优先执行的机会越大,但不是一定优先级高的比优先级低先执行。
线程[2]的优先级为: 10
线程(3)的优先级为: 1
线程<1>的优先级为: 5
线程<1>的优先级为: 5
线程<1>的优先级为: 5
线程<1>的优先级为: 5
线程[2]的优先级为: 10
线程[2]的优先级为: 10
线程[2]的优先级为: 10
线程[2]的优先级为: 10
线程[2]的优先级为: 10
线程[2]的优先级为: 10
线程(3)的优先级为: 1
线程<1>的优先级为: 5
线程<1>的优先级为: 5
线程<1>的优先级为: 5
线程(3)的优先级为: 1
线程[2]的优先级为: 10
线程(3)的优先级为: 1
线程<1>的优先级为: 5
线程<1>的优先级为: 5
线程(3)的优先级为: 1
线程[2]的优先级为: 10
线程(3)的优先级为: 1
线程<1>的优先级为: 5
线程(3)的优先级为: 1
线程[2]的优先级为: 10
线程(3)的优先级为: 1
线程(3)的优先级为: 1
线程(3)的优先级为: 1
6、interrupt() 方法:让当前线程挂起
说明:
> 通过isInterrupt()方法来判断方法当前线程是否为挂起等待,不要以为它是中断某个线程!它只是线线程发送一个中断信号,让线程在无限等待时(如死锁时)能抛出抛出,从而结束线程,但是如果你吃掉了这个异常,那么这个线程还是不会中断的!
package org.xyz.java.thread.demo02;
/**
* 线程的interrupt方法讲解
* 不要以为它是中断某个线程!它只是线线程发送一个中断信号,让线程在无限等待时(如死锁时)能抛出抛出,从而结束线程,但是如果你吃掉了这个异常,那么这个线程还是不会中断的!
* @author kevin.chen
*
*/
public class InterruptMethod {
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}});
// 启动线程
t.start();
boolean b = t.isInterrupted();
System.out.println("检查线程启动后是否为挂起状态:" + b);
// 让子线程挂起
t.interrupt();
b = t.isInterrupted();
System.out.println("检查线程挂起后是否为挂起状态:" + b);
}
}
7、currentThread() 方法:获取当前线程实例对象
8、setName() 方法:设置线程的名称
9、isAlive() 方法:判断当前线程是否存活,如果是,返回true; 否则,返回false。
10、isDeamon() 方法:判断当前线程是否是主线程,如果是,返回true; 否则,返回false。
11、stop() 方法:使线程停止
说明:已过时,该方法可能会导致死锁
12、destroy() 方法:使线程销毁
说明: 已过时,该方法可能会导致死锁
13、suspend() 方法:让线程挂起
说明:已过时,该方法可能会导致死锁
14、resume() 方法:让线程恢复运行
说明: 已过时,该方法可能会导致死锁
package org.xyz.java.thread.demo02;
public class OtherMethod {
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程其他方法使用...");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
try {
Thread.sleep(1000);
// 判断线程是否存活
isAliveMethod(t);
// 判断线程是否为主线程
isDaemonMethod(t);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 挂起操作
suspendMethod(t);
System.out.println("线程已经挂起");
// 恢复操作
resumeMethod(t);
System.out.println("线程已经恢复");
// 停止操作
stopMethod(t);
System.out.println("线程已经停止");
// 销毁操作
// destroyMethod(t);
System.out.println("线程已经销毁");
// 再次判断线程是否存活
isAliveMethod(t);
}
// 线程isAlive方法使用
public static void isAliveMethod(Thread thread) {
boolean b = thread.isAlive();
System.out.println("当前线程存活状态:" + b);
}
// 线程suspend方法使用
public static void isDaemonMethod(Thread thread) {
boolean b = thread.isDaemon();
System.out.println("当前线程是否为主线程:" + b);
}
// 线程suspend方法使用
public static void suspendMethod(Thread thread) {
thread.suspend();
}
// 线程resume方法使用
public static void resumeMethod(Thread thread) {
thread.resume();
}
// 线程stop方法使用
public static void stopMethod(Thread thread) {
thread.stop();
}
// 线程destroy方法使用
public static void destroyMethod(Thread thread) {
thread.destroy();
}
}
运行结果: destroy() 方法会报 java.lang.NoSuchMethodError 错误,这里暂时屏蔽掉
线程其他方法使用...
当前线程存活状态:true
当前线程是否为主线程:false
线程已经挂起
线程已经恢复
线程已经停止
线程已经销毁
当前线程存活状态:false