一、创建线程(五种方法)
public class ThreadDemo {
static class MyThread extends Thread{
@Override
public void run() {
System.out.println("hello world,我是一个新线程");
while (true) {
}
}
}
// Runnable 本质上就是描述一段要执行的任务代码
static class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("我是一个新线程");
}
}
public static void main(String[] args) {
// 1、显示继承 Thread
/* Thread t = new MyThread();
t.start();
*/
// 2、匿名内部类
/* Thread t = new Thread() {
@Override
public void run() {
System.out.println("我是一个新线程");
}
};
t.start();
*/
// 3、显示创建一个类,实现 Runnable 接口,然后把实例关联到 Thread 上
/*
Thread t = new Thread(new MyRunnable());
t.start();
*/
// 4、通过匿名内部类来实现 Runnable 接口
/* Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("我是一个新线程");
}
};
Thread t = new Thread(runnable);
t.start();
*/
// 5、使用 lambda 表达式来指定要线程执行的内容
Thread t = new Thread(() -> {
System.out.println("我是一个新线程");
});
t.start();
}
}
二、中断(两种)
1、借助一个标志位,此方法比较温和,当收到中断指令时,会将当前循环结束才中断
public class ThreadDemo6 {
private static boolean isQuit = false;
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread() {
@Override
public void run() {
while (!isQuit) {
System.out.println("别烦我,我在转账");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("转账被终止");
}
};
t.start();
Thread.sleep(5000);
// 终止交易
System.out.println("有内鬼,赶快停止交易");
isQuit = true;
}
}
2、Interrupt,此方法比较激进,只要收到中断,立即停止当前正在做的事情
public class ThreadDemo7 {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread() {
@Override
public void run() {
// 直接使用线程内部的标记位来判断
while (!Thread.currentThread().isInterrupted()) {
System.out.println("我在转账中");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
}
};
t.start();
Thread.sleep(5000);
System.out.println("对方是内鬼,停止交易");
t.interrupt();
}
}
三、等待(join)
目的:为了控制线程间结束的先后顺序
public class ThreadDemo8 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("我是线程1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread t2 = new Thread() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("我是线程2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
/*t1.start(); // 执行线程1
t1.join();//等待线程1结束
t2.start(); // 执行线2
t2.join();// 等待线程2结束*/
t1.start();
t2.start();
t1.join();// 等待线程结束,最后执行主线程
t2.join();
System.out.println("结束");
}
}
四、获取线程实例
Thread.currentThread 哪个线程在调用这个方法,获取到的引用就指向哪个线程
当线程是继承 Thread 类的方法来创建的,类似于 this ,如果是其他方法创建,稳妥起见还是要继续使用 currentThread
五、休眠(sleep)
线程A 调用了 sleep 方法,就被阻塞,阻塞到 sleep 指定的时间到,才继续执行
六、线程状态
NEW:说明 Thread 对象有了,但是内核中 PCB 没有,要等调用 start 才有 PCB
RUNNABLE:线程正在 CPU 上执行或是即将到 CPU 上执行(PCB 在就绪状态)
WAITING:wait 方法导致
TEMED_WAITING:sleep 方法导致
BLOCKED:等待锁导致
TERMINATED:Thread 对象 还在,但是 PCB 已经没有了