一.创建线程
1.继承Thread类
继承Thread类来创建一个线程.
class MyThread extends Thread {
public void run() {
System.out.println("运行线程代码");
}
}
创建MyThread类的实例
MyThread t = new MyThread();
t.start();//启动线程
2.实现Runnable接口
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("运行线程代码");
}
创建Thread类实例,调用Thread的构造方法时将Runnable对象作为target参数.
Thread t = new Thread(new MyRunnable());
t.start();//启动线程
3.匿名内部类创建Thread子类对象
Thread t = new Thread() {
@Override
public void run() {
System.out.println("运行线程代码");
}
};
t.start();//启动线程
4.匿名内部类创建Runnable子类对象
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("运行线程代码");
}
});
t.start();//启动线程
5.lambda表达式创建Runnable子类对象
Thread t = new Thread(() -> {
System.out.println("运行线程代码");
});
t.start();//启动线程
二.Thread类及常见的方法
1.Thread的常见构造方法
(1)Thread() : 创建线程对象.
(2)Thread(Runnable target) : 使用Runnable对象创建线程对象.
(3)Thread(String name) : 创建线程对象并命名.
(4)Thread(Runnable target ,String name) : 使用Runnable对象创建线程对象,并命名.
(5)Thread(ThreadGroup group ,Runnable target) : 分组(了解);
2.终止一个线程
方法1 :通过共享标记位来进行沟通
示例:使用自定义的变量来作为标记位.(需要给标志位加上volatile关键字)
public class Demo7 {
private static class MyRunnable implements Runnable {
public volatile boolean isQuit = false;
@Override
public void run() {
while(!isQuit) {
System.out.println(Thread.currentThread().getName() + "别管我,我在转账");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println(Thread.currentThread().getName()+"险些误大事");
}
}
public static void main(String[] args) throws InterruptedException {
MyRunnable target = new MyRunnable();
Thread thread = new Thread(target,"李四");
System.out.println(Thread.currentThread().getName() + "让李四开始转账");
thread.start();
Thread.sleep(10*1000);
System.out.println(Thread.currentThread().getName() + "通知李四,对方是个骗子");
target.isQuit = true;
}
}
方法2
使用Thread.interrupted()或者Thread.currentThread().isInterrupted()代替自定义标志位.
Thread内部包含了一个Boolean类型的变量作为线程是否被中断的标记.
(1)public void interrupt() : 中断对象关联的线程.
(2)public static boolean interrupted() : 判断当前线程的中断标志位是否设置.
(3)public boolean isInterrupted() : 判断对象关联的线程的标志位是否设置.
1.使用thread对象的 interrupted() 方法通知线程结束.
public class Demo7 {
private static class MyRunnable implements Runnable {
//public volatile boolean isQuit = false;
@Override
public void run() {
while(!Thread.interrupted()) {
System.out.println(Thread.currentThread().getName() + "别管我,我在转账");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println(Thread.currentThread().getName() + "有内鬼,停止交易");
break;
}
}
System.out.println(Thread.currentThread().getName()+"险些误大事");
}
}
public static void main(String[] args) throws InterruptedException {
MyRunnable target = new MyRunnable();
Thread thread = new Thread(target,"李四");
System.out.println(Thread.currentThread().getName() + "让李四开始转账");
thread.start();
Thread.sleep(10*1000);
System.out.println(Thread.currentThread().getName() + "通知李四,对方是个骗子");
thread.interrupt();
}
}
thread收到通知的方式有两种:
1.如果线程因为调用wait / join / sleep 等方法而阻塞挂起,则以InterruptedException 异常的形式通知,清除中断标志.
1)当出现InterruptedException 的时候,要不要结束线程取决于catch中代码的写法.可以选择忽略,这个异常,也可以跳出循环结束线程.
2.否则,只是内部的一个中断标志位被设置,thread可以通过
1) Thread.current Thread().isInterrupted()判断指定线程的中断标志位被设置,不清除中断标志位这种方式通知收到的更及时,即使线程正在sleep也可以马上收到.
3.等待一个线程-join()
有时,我们需要等待⼀个线程完成它的⼯作后,才能进⾏⾃⼰的下⼀步⼯作.
public class TestDemo3{
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
int n = 5;
for (int i = 0; i < n; i++) {
System.out.println("我是一个线程, 正在工作中...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("线程执行结束");
});
t.start();
t.join(); // 线程等待
System.out.println("这是主线程, 期望在 thread 结束后打印");
}
}
方法:
public void join() | 等待线程结束 |
public void join(long millis) | 等待线程结束,最多等待millis毫秒 |
public void join(long millis,int nanos) | 同上 |